我必须使用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>
答案 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)