5

次のコードがあります。

def application(env, start_response):
    path = process(env)
    fh = open(path,'r')
    start_response('200 OK', [('Content-Type','application/octet-stream')])
    return fbuffer(fh,10000)


def fbuffer(f, chunk_size):
    '''Generator to buffer file chunks'''  
    while True:
        chunk = f.read(chunk_size)      
        if not chunk: break
        yield chunk

それが正しいかどうかはわかりませんが、インターネットで見つけた断片的な情報から、うまくいくはずだと思いました. 基本的に、ファイルをチャンクでストリーミングしたいので、アプリケーション関数からジェネレーターを返します。ただし、これはヘッダーを出力するだけで、実際にデータを送り返すことはありません。誰でも理由を教えてもらえますか?

または、これが完全に間違っている場合、これを行う最善の方法は何ですか? 作業するファイルは数ギガバイトになる可能性があるため、ファイル全体をメモリにバッファリングすることはできません。

第 3 の質問: 出力が完了したら、ファイルを閉じる最善の方法は何ですか? 私が投稿したコードでは、実際にファイルを閉じる方法がわかりません。

(uWSGI 1.2.4でpython 3.2.3を実行しています)

4

1 に答える 1

7

注意を怠ると、uwsgi はエラーが漏れないように注意していますが、アプリケーションをより厳密な実装 (たとえば python で提供されているもの) で実行するとwsgiref.simple_server、問題をより簡単に確認できます。

Serving <function application at 0xb65848> http://0.0.0.0:8000
Traceback (most recent call last):
  File "/usr/lib64/python3.2/wsgiref/handlers.py", line 138, in run
    self.finish_response()
  File "/usr/lib64/python3.2/wsgiref/handlers.py", line 179, in finish_response
    self.write(data)
  File "/usr/lib64/python3.2/wsgiref/handlers.py", line 264, in write
    "write() argument must be a bytes instance"
AssertionError: write() argument must be a bytes instance
localhost.localdomain - - [04/Aug/2012 16:27:08] "GET / HTTP/1.1" 500 59

問題は、wsgi では、HTTP ゲートウェイとの間で送受信されるデータを として提供する必要があることbytesですが、 を使用するopen(path, 'r')と、Python 3 は読み取ったデータを便利に Unicode に変換します。Python 3strでは、デフォルトのエンコーディングを使用します。

変化

fh = open(path, 'r')

fh = open(path, 'rb')
#                 ^

それを修正します。

于 2012-08-04T20:32:06.677 に答える