【问题标题】:Werkzeug response too slowWerkzeug 响应太慢
【发布时间】:2013-05-22 18:08:56
【问题描述】:

我有以下 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 秒)。

为什么这 3 种方法之间有这么大的区别?
为什么第三种方法这么慢?

【问题讨论】:

    标签: python apache mod-wsgi httpresponse werkzeug


    【解决方案1】:

    经过一些测试,我想我已经弄清楚了其中的奥秘。

    @Armin 已经解释了为什么会这样...

    response = Response()
    response.response = fileObj.read()
    

    ...太慢了。但这并不能解释为什么会这样......

    response = Response( response=fileObj.read() )
    

    ...太快了。它们看起来是一回事,但显然它们不是。否则速度不会有那么大的差异。

    这里的关键在这部分文档中:http://werkzeug.pocoo.org/docs/wrappers/

    响应可以是任何类型的可迭代或字符串。如果它是一个字符串,它被认为是一个可迭代的,其中一个项目是传递的字符串。

    即当你给构造函数一个字符串时,它会被转换为一个可迭代的,字符串是它唯一的元素。但是当你这样做时:response.response = fileObj.read(),字符串被视为原样。

    所以要让它表现得像构造函数,你必须这样做:

    response.response = [ fileObj.read() ]
    

    现在文件已尽快发送。

    【讨论】:

      【解决方案2】:

      答案很简单:

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

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

      from werkzeug.wsgi import wrap_file
      return Response(wrap_file(environ, yourfile), direct_passthrough=True)
      

      direct_passthrough 标志是必需的,这样响应对象就不会尝试遍历文件包装器,而是让 WSGI 服务器保持不变。

      【讨论】:

      • 我展示的第一个方法:Response( response=fileObj.read() ) 将响应设置为一个字符串,它只需要 500 毫秒。这对我来说似乎很快。
      【解决方案3】:

      我无法准确回答为什么会发生这种情况,但http://werkzeug.pocoo.org/docs/wsgi/#werkzeug.wsgi.wrap_file 可能有助于解决您的潜在问题。

      【讨论】:

        猜你喜欢
        • 2021-01-12
        • 2013-10-30
        • 1970-01-01
        • 1970-01-01
        • 2020-06-25
        • 2018-11-16
        • 2020-01-03
        • 2021-08-01
        • 1970-01-01
        相关资源
        最近更新 更多