在常规python脚本中使用tornado异步代码

时间:2013-10-29 23:29:28

标签: python asynchronous tornado coroutine

我有一些使用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

2 个答案:

答案 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)