我创建了一个简单的测试应用程序来检查龙卷风中的超时导入龙卷风ioloop导入龙卷风.web
class LoopHandler(tornado.web.RequestHandler):
def get(self):
while (True):
print ("in loop")
self.write("Loop, Handler")
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
(r"/loop", LoopHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
然后我打电话http://localhost:8888/loop端点永远不会响应,因为无限循环的问题在于http://localhost:8888/也没有回应。问题是为什么会发生这种情况,如何解决?
编辑
更新解决问题的代码
import tornado.ioloop
import tornado.web
@unblock
class LoopHandler(tornado.web.RequestHandler):
def get(self):
while (True):
print ("in loop")
return "Loop, Handler"
@unblock
class MainHandler(tornado.web.RequestHandler):
def get(self):
return "Hello, world"
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
(r"/loop", LoopHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
#unblock.py
import tornado.web
import tornado.ioloop
from concurrent.futures import ThreadPoolExecutor
from functools import partial, wraps
EXECUTOR = ThreadPoolExecutor(max_workers=4)
def unblock(f):
@tornado.web.asynchronous
@wraps(f)
def wrapper(*args, **kwargs):
self = args[0]
def callback(future):
self.write(future.result())
self.finish()
EXECUTOR.submit(
partial(f, *args, **kwargs)
).add_done_callback(
lambda future: tornado.ioloop.IOLoop.instance().add_callback(
partial(callback, future)))
return wrapper
这些是异步编程的基础。为了给您指明正确的方向,请查看reactor模式,尤其是事件循环。
reactor模式是事件驱动的一种实现技术建筑学简单地说,它使用单线程事件循环阻止资源发射事件并将其分派到相应的处理程序和回调。
函数LoopHandler
和MainHandler
都在同一事件循环中处理,因此MainHandler
会排队,但从不执行,因为事件循环正忙于执行LoopHandler
。
异步编程中的一个挑战(至少对我来说)是要小心阻止调用,如SQLAlchemy
的数据库操作、文件操作、昂贵的计算等。有一些有趣的方法使用线程池来解决这个问题,但你不需要它们就可以开始了。
啊,如果你被我链接的维基文章的第一句话绊倒了,看看这里,了解并行和并发之间的区别。这对我帮助很大