如果IOStream.connect不起作用,则停止IOLoop

时间:2015-01-29 14:26:42

标签: python tornado

我有一个脚本需要异步连接到TCP服务器并使用TornadoWeb(3.2)发送一些数据。

这是简短版本:

import tornado.ioloop
import tornado.iostream
import socket

def main():
    def do_something():
        print 'doing something'
        stream.close()
        tornado.ioloop.IOLoop.instance().stop()

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    stream = tornado.iostream.IOStream(s)
    stream.connect(("10.0.0.0", 80), do_something)

main()
tornado.ioloop.IOLoop.instance().start()

如果stream.connect失败,我无法关闭IOLoop,脚本就会挂起。 首先,我认为在stream.connect之后关闭IOLoop可能会有效,但它实际上会在连接发生之前关闭IOLoop并退出脚本。

此外,似乎我不能尝试/除此之外,因为stream.connect在发生故障时不会引发任何异常,而是什么都不返回:

# I stripped out the comments
def connect(self, address, callback=None, server_hostname=None):
    self._connecting = True
    try:
        self.socket.connect(address)
    except socket.error as e:
        if (e.args[0] != errno.EINPROGRESS and
                e.args[0] not in _ERRNO_WOULDBLOCK):
            gen_log.warning("Connect error on fd %d: %s",
                            self.socket.fileno(), e)
            self.close(exc_info=True)
            return
    self._connect_callback = stack_context.wrap(callback)
    self._add_io_state(self.io_loop.WRITE)

所以,主要的问题是:无论stream.connect是否有效,我怎样才能关闭IOLoop,但只有在stream.connect完成工作后才能关闭?

1 个答案:

答案 0 :(得分:1)

如果连接失败,将调用流的close_callback而不是connect回调,因此在connect()之前调用stream.set_close_callback()来设置错误处理程序。

但是,对于像这样的代码,我建议使用协程而不是回调,这看起来像:

import socket
import tornado.gen
import tornado.ioloop
import tornado.iostream

@tornado.gen.coroutine
def main():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    stream = tornado.iostream.IOStream(s)
    try:
        yield stream.connect(('10.0.0.0', 80))
    except Exception as e:
        print("connection failed: %s" % e)
    print("doing something")
    stream.close()

if __name__ == '__main__':
    tornado.ioloop.IOLoop.current().run_sync(main)

协程通常具有更简单的错误处理,run_sync()将IOLoop的生命周期与主函数的生命周期联系起来。