Python 2 Tornado异步方法

时间:2019-01-13 14:41:49

标签: python-2.7 tornado

我必须使用Python 2进行异步调用。

我正在使用Tornado来完成此操作,但是如果有更好的工具,我可以更换工具。

以下代码在后台异步运行我的sleep 2 && echo hi命令

from tornado import gen
import subprocess
import time

@gen.coroutine
def longProcess():
    bashCommand = "sleep 5 && echo hi"
    process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
    output, error = process.communicate()

    yield output

futures = [longProcess() for x in range(0, 5)]

while True:
    if all(x.done() == True for x in futures):
        break
    time.sleep(1)

print('All futures resolved')

问题是在我的bash命令完成之前,x.done()会为所有期货返回True

如何将process.communicate()变成未来(只有在关键字“ hi”可用时才能完成),以便我可以等待所有未来完成,然后从期货中获取输出? / p>

1 个答案:

答案 0 :(得分:0)

使用Tornado自己的process.Subprocess类,该类是stdlib的subprocess.Popen的包装。

示例:

from tornado import process

@gen.coroutine
def longProcess():
    bashCommand = "sleep 5 && echo hi"

    proc = process.Subprocess(bashCommand.split(), stdout=subprocess.PIPE)

    yield proc.wait_for_exit() # `wait_for_exit` returns a future 
                               # which you can yield. Basically, it means
                               # you can wait for the process to complete
                               # without blocking the server

    return proc.stdout.read() # return the result of the process

    # for Python 2:
    # you can't return from a generator
    # instead use this:
    # raise gen.Return(proc.stdout.read())

您不需要while循环。您可以将该代码移到其他协程中,并产生futures的列表。像这样:

@gen.coroutine
def main():
    futures = [longProcess() for x in range(0, 5)]

    results = yield futures # this coroutine will not move further 
                            # until every future in the list 
                            # `futures` is resolved

    for result in results:
        print(result)

    print('All futures resolved')

请注意,请勿使用time.sleep。它将阻止整个服务器。而是使用异步等效项gen.sleep-yield gen.sleep(1)