如何“刷新”Pylons中的响应(类似于ASP Response.Write)

时间:2010-03-11 03:57:29

标签: python http streaming pylons

我有一个通过jQuery $ .ajaxSubmit()调用的Pylons控制器。它执行长时间运行的操作,我想让它在整个输出可用之前返回进度消息。作为一个简单的概念证明,我试过这个:

response.body_file.write('<script>OnExecutionProgress("Starting");</script>\n')
time.sleep(2)
response.body_file.write('<script>OnExecutionProgress("Finished");</script>\n')

但是,这不会立即将第一条消息返回给客户端 - 整个输出仅在结尾处返回。

我之前在ASP.NET中使用Response.Write()Response.Flush()完成了类似的操作,但效果很好。但是,在Pylons中调用response.body_file.flush()似乎没有任何区别。

3 个答案:

答案 0 :(得分:1)

本地,HTTP不支持您希望的“流式传输” - 它是一个请求/响应协议,并且没有符合协议的方式来发送“响应的一部分”。相反,您可能正在寻找所谓的Comet技术。 “铁塔彗星”的一个简单例子是here

答案 1 :(得分:0)

这绝对是一个黑客攻击,但在pylons中它的工作方式与ASP.NET相同。我在Paste服务器上测试了它。

正如Alex Martelli所说,在这种情况下使用Comet会更好。按块添加脚本块可能会导致以下问题:

  1. 它不受支持且依赖于服务器实现;
  2. 不可靠,因为您无法处理连接超时;
  3. 服务器需要为每个连接分配单独的线程,这可能成为高负载站点的性能瓶颈。
  4. 首先,您应该关闭development.ini中的调试:

    debug = false
    

    这是一个控制器代码:

    class HelloController(BaseController):
        def index(self):
            header = '''\
    <html><head><title>test page</title>
    <script type="text/javascript">
    function foo(i) {
    document.getElementById('counter').innerHTML = i;
    }
    </script>
    </head>
    <body>
    <div id="counter">
    </div>
    '''
            footer = '''\
    </body>
    </html>
    '''
            progress = ('<script>foo(%i);</script>' % i for i in xrange(0,101,2))
            def f():
                yield header
                for script in progress:
                    time.sleep(1)
                    yield script
                yield footer
            return f()
    

答案 2 :(得分:0)

您可以一次“收益”您的结果块。 尝试编写一个一次产生结果块的生成器,它可能会起作用。它使用http://en.wikipedia.org/wiki/Chunked_transfer_encoding