Werkzeug的反应太慢了

Get*_*ree 4 python apache mod-wsgi httpresponse werkzeug

我有以下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
Run Code Online (Sandbox Code Playgroud)

我要关注的部分是这一部分:

response = Response( response=fileObj.read() )
Run Code Online (Sandbox Code Playgroud)

在这种情况下,响应大约需要500毫秒(C:\test.pdf是一个4 MB的文件.Web服务器在我的本地机器上).

但是,如果我重写这一行:

response = Response()
response.response = fileObj
Run Code Online (Sandbox Code Playgroud)

现在响应大约需要1500毫秒.(慢3倍)

如果这样写:

response = Response()
response.response = fileObj.read()
Run Code Online (Sandbox Code Playgroud)

现在响应大约需要80秒(这是正确的,80 SECONDS).

为什么3种方法之间存在很大差异?
为什么第三种方法太慢?

Arm*_*her 8

答案很简单:

  • x.read() < - 将整个文件读入内存,效率低下
  • 设置对文件的响应:非常低效,因为该对象的协议是迭代器.所以你将逐行发送文件.如果它是二进制的,你甚至会随机发送大小的块.
  • 设置response为字符串:坏主意.它是前面提到的迭代器,因此您现在将字符串中的每个字符作为单独的数据包发送.

正确的解决方案是将文件包装在WSGI服务器提供的文件包装器中:

from werkzeug.wsgi import wrap_file
return Response(wrap_file(environ, yourfile), direct_passthrough=True)
Run Code Online (Sandbox Code Playgroud)

direct_passthrough标志是必需的,以便响应对象不会尝试迭代文件包装器,但不会使WSGI服务器保持不变.