我有以下Werkzeug应用程序,用于将文件返回给客户端:
from werkzeug.wrappers import Request, Response
@Request.application
def application(request):
fileObj = file(r'C:\test.pdf','rb')
response = Response( response=fileObj.read() )
response.headers['content-type'] = 'application/pdf'
return response我想要关注的部分是这一个:
response = Response( response=fileObj.read() )在这种情况下,响应大约需要500毫秒(C:\test.pdf是一个4 MB的文件。Web服务器在我的本地机器上)。
但如果我将这一行重写为:
response = Response()
response.response = fileObj现在响应大约需要1500毫秒。(速度慢3倍)
如果这样写的话:
response = Response()
response.response = fileObj.read()现在响应大约需要80秒(没错,80秒)。
为什么这三种方法之间有这么大的差异?
为什么第三种方法这么慢呢?
发布于 2013-05-28 10:40:50
经过一些测试,我想我已经发现了其中的奥秘。
@Armin已经解释了为什么.
response = Response()
response.response = fileObj.read()...is太慢了。但这不能解释为什么这..。
response = Response( response=fileObj.read() )...is太快了。它们看起来是一回事,但显然不是。否则,在速度上就不会有那么大的差别。
这里的关键在于文档的这一部分:http://werkzeug.pocoo.org/docs/wrappers/
响应可以是任何类型的可迭代或字符串。如果它是一个字符串,它被认为是一个带有一个项目的迭代器,这就是传递的字符串。
也就是说,当你给构造器一个字符串时,它被转换成一个迭代器,这个字符串是它唯一的元素。但当您执行以下操作时:response.response = fileObj.read(),该字符串将按原样处理。
因此,要使其行为类似于构造函数,您必须这样做:
response.response = [ fileObj.read() ]现在,文件会以最快的速度发送。
发布于 2013-05-28 07:41:54
这个问题的答案很简单:
x.read() <-将整个文件读入内存,inefficientresponse设置为字符串:这是个坏主意。如前所述,它是一个迭代器,因此您现在将字符串中的每个字符作为单独的包发送。正确的解决方案是将文件包装在WSGI服务器提供的文件包装器中:
from werkzeug.wsgi import wrap_file
return Response(wrap_file(environ, yourfile), direct_passthrough=True)direct_passthrough标志是必需的,这样响应对象就不会试图遍历文件包装器,而是让WSGI服务器保持不变。
发布于 2013-05-28 07:02:45
我不能给你一个确切的答案,为什么会发生这种情况,但是http://werkzeug.pocoo.org/docs/wsgi/#werkzeug.wsgi.wrap_file可能会帮助你解决下属的问题。
https://stackoverflow.com/questions/16780731
复制相似问题