【发布时间】:2017-09-28 22:09:01
【问题描述】:
我正在尝试编写用于 Tornado 应用程序的异步方法。我的方法需要管理一个可以并且应该在对函数的其他调用之间共享的连接。该连接由awaiting 创建。为了解决这个问题,我使用了asyncio.Lock。但是,对我的方法的每次调用都会等待锁定。
经过几个小时的试验,我发现了一些东西,
- 如果锁定块中没有
awaits,则一切正常 -
tornado.ioloop.IOLoop.configure('tornado.platform.asyncio.AsyncIOLoop')没有帮助 -
tornado.platform.asyncio.AsyncIOMainLoop().install()允许它工作,无论事件循环是否以tornado.ioloop.IOLoop.current().start()或asyncio.get_event_loop().run_forever()启动
以下是一些示例代码,除非您取消注释 AsyncIOMainLoop().install(),否则这些示例代码将无法使用:
import tornado.ioloop
import tornado.web
import tornado.gen
import tornado.httpclient
from tornado.platform.asyncio import AsyncIOMainLoop
import asyncio
import tornado.locks
class MainHandler(tornado.web.RequestHandler):
_lock = asyncio.Lock()
#_lock = tornado.locks.Lock()
async def get(self):
print("in get")
r = await tornado.gen.multi([self.foo(str(i)) for i in range(2)])
self.write('\n'.join(r))
async def foo(self, i):
print("Getting first lock on " + i)
async with self._lock:
print("Got first lock on " + i)
# Do something sensitive that awaits
await asyncio.sleep(0)
print("Unlocked on " + i)
# Do some work
print("Work on " + i)
await asyncio.sleep(0)
print("Getting second lock on " + i)
async with self._lock:
print("Got second lock on " + i)
# Do something sensitive that doesnt await
pass
print("Unlocked on " + i)
return "done"
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
#AsyncIOMainLoop().install() # This will make it work
#tornado.ioloop.IOLoop.configure('tornado.platform.asyncio.AsyncIOLoop') # Does not help
app = make_app()
app.listen(8888)
print('starting app')
tornado.ioloop.IOLoop.current().start()
我现在知道tornado.locks.Lock() 存在并且有效,但我很好奇为什么asyncio.Lock 无效。
【问题讨论】:
标签: python locking tornado python-asyncio