【问题标题】:Python 2 Tornado asychronous methodPython 2 Tornado 异步方法
【发布时间】:2019-01-13 14:41:49
【问题描述】:

我必须使用 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”可用时才完成),以便我可以等待所有期货都完成,然后从期货中获取输出?

【问题讨论】:

    标签: python-2.7 tornado


    【解决方案1】:

    使用 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)

    【讨论】:

    • 使用我得到的代码:return proc.stdout.read() # return the result of the process SyntaxError: 'return' with argument inside generator
    • @ClickThisNick 啊,您必须使用 Python 2。代替 return 语句,您需要使用 -- raise gen.Return(proc.stdout.read())
    • 这仍然给出错误*** AttributeError: 'Subprocess' object has no attribute 'wait_for_exit'。由于我使用的是 Python2,所以我必须使用 tornado 4,也许这适用于 tornado 5(不适用于 Python 2)
    • @ClickThisNick wait_for_exit 在 Tornado 4.2 中添加。顺便说一句,Tornado 5 也支持 Python 2。
    猜你喜欢
    • 1970-01-01
    • 2012-09-04
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-20
    相关资源
    最近更新 更多