我有一个脚本需要异步连接到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完成工作后才能关闭?
答案 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的生命周期与主函数的生命周期联系起来。