【问题标题】:WSGI file streaming with a generator使用生成器进行 WSGI 文件流式传输
【发布时间】:2012-08-04 19:27:54
【问题描述】:

我有以下代码:

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

我不确定它是否正确,但我在互联网上找到的零碎信息让我认为它应该可以工作。基本上我想以块的形式输出一个文件,为此我从我的应用程序函数中传回一个生成器。但是这只会打印出标题,实际上并没有发回任何数据,谁能告诉我这是为什么?

或者,如果这是完全错误的,那么最好的方法是什么?我无法在内存中缓冲整个文件,因为我要处理的文件可能有千兆字节。

第三个问题:完成输出后关闭文件的最佳方法是什么?在我发布的代码中,我看不到实际关闭文件。

(我正在运行带有 uWSGI 1.2.4 的 python 3.2.3)

【问题讨论】:

标签: python wsgi large-files


【解决方案1】:

不小心,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 3中是@ 987654325@,使用默认编码。

改变

fh = open(path, 'r')

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

修复它。

【讨论】:

  • 啊,谢谢!这是有道理的......你介意评论我关于关闭文件的问题吗?将关闭命令放在生成器中的 break 语句之前会起作用吗?还是有更好的方法?
  • 是的,这是合理的做法。还可以查看environ['wsgi.file_wrapper'] 功能,它可能允许您在支持它的平台上使用sendfile(),以提高效率。
猜你喜欢
  • 1970-01-01
  • 2019-07-18
  • 1970-01-01
  • 2018-01-13
  • 1970-01-01
  • 2014-05-09
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多