【问题标题】:Asyncio issues running an external command运行外部命令的 Asyncio 问题
【发布时间】:2021-04-21 15:42:16
【问题描述】:

我希望在异步协程(以及其他协程)中运行外部命令。目的是让其他协程(作为任务运行)在此 coro 被阻止/执行外部命令时继续运行。 这是我运行两个协程的测试代码:我想同时运行两个协程,并在运行后打印外部命令的输出。

import asyncio

async def checker():
    for i in range(30):
        print(f'Checker Iteration: {i}')
        await asyncio.sleep(1)

async def foo():
    proc = await asyncio.create_subprocess_exec("speedtest", stdout=asyncio.subprocess.PIPE)
    await asyncio.gather(asyncio.to_thread(proc))
    print(f'Process Return Code: {proc.returncode} and Output: \n{proc.stdout}')

async def main():
    t1 = asyncio.create_task(checker())
    t2 = asyncio.create_task(foo())
    await(t1)

        
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

但是,当我运行上面的代码时,我得到:

    Checker Iteration: 0
    Checker Iteration: 1
    Checker Iteration: 2
    ...
    ...
    Checker Iteration: 29
    Task exception was never retrieved
    future: <Task finished name='Task-3' coro=<foo() done, defined at C:\Users\Sri         Vedurumudi\code\speedtest\speedtest.py:8> exception=TypeError("'Process' object is not callable")>
    Traceback (most recent call last):
      File "C:\Users\Sri Vedurumudi\code\speedtest\speedtest.py", line 12, in foo
        await asyncio.gather(asyncio.to_thread(proc))
      File "C:\Program Files\Python39\lib\asyncio\threads.py", line 25, in to_thread
        return await loop.run_in_executor(None, func_call)
      File "C:\Program Files\Python39\lib\concurrent\futures\thread.py", line 52, in run
        result = self.fn(*self.args, **self.kwargs)
    TypeError: 'Process' object is not callable

Python(使用 3.9.4)专家能否为我指明正确的方向?

【问题讨论】:

  • 有几个问题。从一个刚刚成功运行“speedtest”外部程序的简单协程开始。在下一步中添加多个任务。
  • 谢谢@VPfB,我刚刚发布了对我有用的内容。你能提出这种方法的任何问题吗?显然我没有处理异常或引入超时来控制流氓进程。
  • 我没有运行它,但它看起来不错。我想建议 asyncio.run(main()) 作为启动程序的更简单方法。

标签: python subprocess python-asyncio


【解决方案1】:

这似乎是有效的。但是,如果您发现代码有任何问题,请告诉我。我发布这个主要是为了将来参考或类似情况的任何人。显然,我没有处理错误或引入超时来检查恶意可执行文件。

import asyncio

async def checker():
    for i in range(40):
        print(f'Checker Iteration: {i}')
        await asyncio.sleep(1)

async def foo():
    proc = await asyncio.create_subprocess_exec("speedtest", stdout=asyncio.subprocess.PIPE)
    # Wait for the process to complete
    await proc.wait()   
    # Read the output
    output = await proc.stdout.read(-1)
    print(f'Process Return Code: {proc.returncode} and Output: \n{output}')


async def main():
    t1 = asyncio.create_task(checker())
    t2 = asyncio.create_task(foo())

    await asyncio.gather(t2,t1)


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

【讨论】:

    猜你喜欢
    • 2020-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多