在龙卷风中将 web.asynchronous 代码转换为 gen.coroutine
Converting web.asynchronous code to gen.coroutine in tornado
我想将我当前的 Tornado 应用程序从使用 @web.asynchronous 转换为 @gen.coroutine。当 IOLoop 迭代中发生特定变量更改时,将调用我的异步回调。 Tornado 文档中的当前示例解决了 I/O 问题,但在我的例子中,它是我感兴趣的变量。我希望协程在变量更改时醒来。我的应用程序看起来像下面显示的代码。
注:我只能用Python2.
# A transaction is a DB change that can happen
# from another process
class Transaction:
def __init__(self):
self.status = 'INCOMPLETE'
self.callback = None
# In this, I am checking the status of the DB
# before responding to the GET request
class MainHandler(web.RequestHandler):
def initialize(self, app_reference):
self.app_reference = app_reference
@web.asynchronous
def get(self):
txn = Transaction()
callback = functools.partial(self.do_something)
txn.callback = callback
self.app_reference.monitor_transaction(txn)
def do_something(self):
self.write("Finished GET request")
self.finish()
# MyApp monitors a list of transactions and adds the callback
# 'transaction.callback' when transactions status changes to
# COMPLETE state.
class MyApp(Application):
def __init__(self, settings):
self.settings = settings
self._url_patterns = self._get_url_patterns()
self.txn_list = [] # list of all transactions being monitored
Application.__init__(self, self._url_patterns, **self.settings)
IOLoop.current().add_callback(self.check_status)
def monitor_transaction(self, txn):
self.txn_list.append(txn)
def check_status(self):
count = 0
for transaction in self.txn_list:
transaction.status = is_transaction_complete()
if transaction.status is 'COMPLETE':
IOLoop.current().add_callback(transaction.callback)
self.txn_list.pop(count)
count += 1
if len(self.txn_list):
IOloop.current().add_callback(self.check_status)
# adds 'self' to url_patterns
def _get_url_patterns(self):
from urls import url_patterns
modified_url_patterns = []
for url in url_patterns:
modified_url_patterns.append( url + ({ 'app_reference': self },))
return modified_url_patterns
如果我理解正确使用 gen.coroutine 编写,则应将 get 修改为
@gen.coroutine
def get(self):
txn = Transaction()
response = yield wake_up_when_transaction_completes()
# respond to GET here
我的问题是我不确定如何仅在状态更改时唤醒例程并且我不能使用循环,因为它会阻塞 tornado 线程。基本上我想从 IOLoop 迭代中通知。
def check_status():
for transaction in txn_list:
if transaction.status is 'COMPLETE':
NOTIFY_COROUTINE
听起来像是新 tornado.locks 的工作!上周与 Tornado 4.2 一起发布:
为此使用事件:
from tornado import locks, gen
event = locks.Event()
@gen.coroutine
def waiter():
print("Waiting for event")
yield event.wait()
print("Done")
@gen.coroutine
def setter():
print("About to set the event")
event.set()
关于事件界面的更多信息:
http://tornado.readthedocs.org/en/latest/locks.html#tornado.locks.Event
我想将我当前的 Tornado 应用程序从使用 @web.asynchronous 转换为 @gen.coroutine。当 IOLoop 迭代中发生特定变量更改时,将调用我的异步回调。 Tornado 文档中的当前示例解决了 I/O 问题,但在我的例子中,它是我感兴趣的变量。我希望协程在变量更改时醒来。我的应用程序看起来像下面显示的代码。
注:我只能用Python2.
# A transaction is a DB change that can happen
# from another process
class Transaction:
def __init__(self):
self.status = 'INCOMPLETE'
self.callback = None
# In this, I am checking the status of the DB
# before responding to the GET request
class MainHandler(web.RequestHandler):
def initialize(self, app_reference):
self.app_reference = app_reference
@web.asynchronous
def get(self):
txn = Transaction()
callback = functools.partial(self.do_something)
txn.callback = callback
self.app_reference.monitor_transaction(txn)
def do_something(self):
self.write("Finished GET request")
self.finish()
# MyApp monitors a list of transactions and adds the callback
# 'transaction.callback' when transactions status changes to
# COMPLETE state.
class MyApp(Application):
def __init__(self, settings):
self.settings = settings
self._url_patterns = self._get_url_patterns()
self.txn_list = [] # list of all transactions being monitored
Application.__init__(self, self._url_patterns, **self.settings)
IOLoop.current().add_callback(self.check_status)
def monitor_transaction(self, txn):
self.txn_list.append(txn)
def check_status(self):
count = 0
for transaction in self.txn_list:
transaction.status = is_transaction_complete()
if transaction.status is 'COMPLETE':
IOLoop.current().add_callback(transaction.callback)
self.txn_list.pop(count)
count += 1
if len(self.txn_list):
IOloop.current().add_callback(self.check_status)
# adds 'self' to url_patterns
def _get_url_patterns(self):
from urls import url_patterns
modified_url_patterns = []
for url in url_patterns:
modified_url_patterns.append( url + ({ 'app_reference': self },))
return modified_url_patterns
如果我理解正确使用 gen.coroutine 编写,则应将 get 修改为
@gen.coroutine
def get(self):
txn = Transaction()
response = yield wake_up_when_transaction_completes()
# respond to GET here
我的问题是我不确定如何仅在状态更改时唤醒例程并且我不能使用循环,因为它会阻塞 tornado 线程。基本上我想从 IOLoop 迭代中通知。
def check_status():
for transaction in txn_list:
if transaction.status is 'COMPLETE':
NOTIFY_COROUTINE
听起来像是新 tornado.locks 的工作!上周与 Tornado 4.2 一起发布:
为此使用事件:
from tornado import locks, gen
event = locks.Event()
@gen.coroutine
def waiter():
print("Waiting for event")
yield event.wait()
print("Done")
@gen.coroutine
def setter():
print("About to set the event")
event.set()
关于事件界面的更多信息:
http://tornado.readthedocs.org/en/latest/locks.html#tornado.locks.Event