我有一些使用tornado gen.coroutine
的异步函数,我通常将其用作基于龙卷风的Web应用程序的一部分。但是,我想从一个普通的旧python脚本中调用它们中的一些来执行一些管理任务。我该怎么做?
from tornado import gen
import some_internal_stuff
@gen.coroutine
def myfunc(x):
y = yield some_internal_stuff.another_async_func(x)
raise gen.Return(y)
if __name__ == "__main__":
# What do I put here to call myfunc(1) and get the async return value?
pass
更新
更具体的例子:
from tornado import gen
@gen.coroutine
def another_async_func(x):
print "aaf"
raise gen.Return(x + 1)
@gen.coroutine
def myfunc(x):
print "myfunc"
y = yield another_async_func(x)
print "back"
raise gen.Return(y)
def callback(y):
print "Callback called with %d" % y
if __name__ == "__main__":
myfunc(1, callback=callback)
运行此输出:
myfunc
aaf
答案 0 :(得分:17)
run_sync
中有一个内置方法IOLoop
来运行一个调用,然后停止循环,所以只需添加一个事件循环就可以了。普通的python脚本,如果你在PYTHONPATH中有龙卷风。
用具体的例子:
from tornado import gen, ioloop
@gen.coroutine
def another_async_func(x):
print "aaf"
raise gen.Return(x + 1)
@gen.coroutine
def myfunc(x):
print "myfunc"
y = yield another_async_func(x)
print "back"
raise gen.Return(y)
@gen.coroutine
def main():
y = yield myfunc(1)
print "Callback called with %d" % y
if __name__ == "__main__":
ioloop.IOLoop.instance().run_sync(main)
输出:
myfunc
aaf
back
Callback called with 2
请注意run_sync
不能很好地嵌套;如果您在同一个run_sync
的{{1}}调用的函数中调用run_sync
,则内部调用的完成将停止IOLoop
,之后不再IOLoop
秒内部召唤将返回。
答案 1 :(得分:1)
这是使用线程的另一种可能性,它可以根据问题的复杂性和您的需求而工作:
if __name__ == "__main__":
import threading, time
# The tornado IO loop doesn't need to be started in the main thread
# so let's start it in another thread:
t = threading.Thread(target=IOLoop.instance().start)
t.daemon = True
t.start()
myfunc(1, callback=callback)
# now the main loop needs wait; you can do that by polling a value, sleeping,
# or waiting on a lock. I've chosen to sleep here, but a lock is probably more
# appropriate; and, once computation is done, release the lock.
time.sleep(2)