【问题标题】:finally block in tornado gen engine not works最后阻止龙卷风发电机引擎不起作用
【发布时间】:2012-12-19 01:18:33
【问题描述】:

假设,(使用龙卷风)一个人想要将大数据传输到慢速客户端,并打印传输的数据量。为此,我编写了这个简单的代码:

from tornado import web, ioloop, gen

class MainHandler(web.RequestHandler):
    @web.asynchronous
    @gen.engine
    def get(self):
        print '( start'
        try:
            for i in xrange(100):
                self.write('*' * 100000)  # write ~100KB of data
                yield gen.Task(self.flush)  # wait for reciever to recieve
                print '- wrote', i
        finally:
            print '| finally'
            self.finish()
        print ') finish'

application = web.Application([
    (r"/", MainHandler),
    ])

application.listen(8888)
ioloop.IOLoop.instance().start()

但是这段代码没有按预期工作,例如使用这个简单的客户端:

req = urlopen('http://127.0.0.1:8888/')
sys.exit()  # exit without reading response

服务器输出这个:

( start
- wrote 0
- wrote 1
- wrote 2
WARNING:root:Read error on 7: [Errno 104] Connection reset by peer
WARNING:root:error on read
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/tornado-2.4.1-py2.7.egg/tornado/iostream.py", line 361, in _handle_read
    if self._read_to_buffer() == 0:
  File "/usr/local/lib/python2.7/dist-packages/tornado-2.4.1-py2.7.egg/tornado/iostream.py", line 428, in _read_to_buffer
    chunk = self._read_from_socket()
  File "/usr/local/lib/python2.7/dist-packages/tornado-2.4.1-py2.7.egg/tornado/iostream.py", line 409, in _read_from_socket
    chunk = self.socket.recv(self.read_chunk_size)
error: [Errno 104] Connection reset by peer

finallyfinish 均未打印。

有什么问题?!

更新:

我注意到,如果我为处理程序实现on_connection_close,将调用on_connection_close 回调,并且不会在控制台中打印错误。但是这个功能有什么魔力呢? (我已经在 RequestHandler 上定义了空体)。

还有更大的答案:为什么我的生成器不是closed?是垃圾收集还是不收集? PEP-342 说 finally 块应该在任何情况下执行。

【问题讨论】:

  • 我想生成器还在等待更多的输入?
  • @Martijn 即使我用信号(或 Control+C)关闭服务器,finally 块也不会运行。如何强制 finally 块执行?
  • 我怀疑它确实运行了,但到那时 stdout 已经关闭了。您是否尝试打开一个明确的专用文件进行测试?
  • 不行,用openwrite测试,最后还是没有运行。
  • 有趣又令人困惑。无论我尝试什么,我都不能让 Python 不要在生成器中运行 finally stuite。

标签: python asynchronous generator tornado finally


【解决方案1】:

具有finally 子句的生成器在 Python 版本 __del__ 实现,并且具有其他析构函数的所有限制 - 如果存在引用循环,则不能保证它们会立即执行。在 Python 3.4 中,这一点得到了改进 (http://www.python.org/dev/peps/pep-0442/),并且生成器的 finally 子句运行更加可靠。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多