2012-08-04 49 views
3

我有以下代碼:WSGI文件與發電機流

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 

我不知道它是正確的,但我發現在互聯網上的信息碎片致使我認爲它應該工作。基本上我想以大塊的形式流出一個文件,並做到這一點,我從我的應用程序函數中傳回一個生成器。然而,這隻能打印標題,並不實際發回任何數據,誰能告訴我爲什麼這是?

或者,如果這是完全錯誤的,那麼執行此操作的最佳方法是什麼?我無法在內存中緩衝整個文件,因爲我將要處理的文件可能是千兆字節。

第三個問題:完成輸出後關閉文件的最佳方法是什麼?在我發佈的代碼中,我無法看到實際關閉文件。

(我運行的Python 3.2.3與1.2.4 uWSGI)

+0

http://www.python.org/dev/peps/pep-0333/#id36 – SingleNegationElimination 2012-08-04 19:49:02

+0

或者更直接的鏈接。 http://www.python.org/dev/peps/pep-0333/#optional-platform-specific-file-handling – 2012-08-05 04:31:07

回答

5

如果沒有一定的照顧,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'),巨蟒-3方便轉換讀取爲Unicode數據,在Python 3是什麼str ,使用默認編碼。

改變

fh = open(path, 'r') 

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

修復它。

+0

啊,謝謝!這是有道理的....你介意評論我關於關閉文件的問題嗎?在發電機工作的break語句之前放置close命令?還是有更好的方法來做到這一點? – 2012-08-04 22:35:58

+2

是的,這是一個合理的事情。還可以看看'environ ['wsgi.file_wrapper']'功能,它可以讓您在支持它的平臺上使用'sendfile()',以提高效率。 – SingleNegationElimination 2012-08-05 03:35:46