【问题标题】:How do I properly use asyncio.create_subprocess_shell() in an async def function?如何在 async def 函数中正确使用 asyncio.create_subprocess_shell()?
【发布时间】:2017-04-29 03:52:58
【问题描述】:

我正在尝试编写一个简单的子进程程序,该程序将调用一个长时间运行的 shell 命令,允许其他进程运行,然后在完成后执行一些清理任务。

不幸的是,我只是让 shell 命令在 asyncio 事件循环中正确执行时遇到了错误。行为是它看起来像 python 从不等待 shell 脚本完成运行。我知道 shell 脚本可以工作,因为我可以从提示中手动运行它。我正在运行的 shell 脚本应该会在 3-5 分钟内执行。

这是我的示例程序:

import asyncio 
from asyncio.subprocess import PIPE, STDOUT 
import subprocess 
import signal


def signal_handler(signal, frame):
    loop.stop()
    client.close()
    sys.exit(0)

async def run_async(loop = ''):
    cmd = 'sudo long_running_cmd --opt1=AAAA --opt2=BBBB'

    print ("[INFO] Starting script...")
    await asyncio.create_subprocess_shell(cmd1, stdin = PIPE, stdout = PIPE, stderr = STDOUT)
    print("[INFO] Script is complete.")


loop = asyncio.get_event_loop() 
signal.signal(signal.SIGINT, signal_handler) 
tasks = [loop.create_task(run_async())] 
wait_tasks = asyncio.wait(tasks) 
loop.run_until_complete(wait_tasks)

loop.close()

程序几乎立即运行并失败。此代码生成的错误是:

[INFO] Starting script...
[INFO] Script is complete.
Exception ignored in: <bound method BaseSubprocessTransport.__del__ of <_UnixSubprocessTransport closed pid=5652 running stdin=<_UnixWritePipeTransport closing fd=7 open> stdout=<_UnixReadPipeTransport fd=8 open>>>
Traceback (most recent call last):
  File "/usr/lib/python3.5/asyncio/base_subprocess.py", line 126, in __del__
  File "/usr/lib/python3.5/asyncio/base_subprocess.py", line 101, in close
  File "/usr/lib/python3.5/asyncio/unix_events.py", line 568, in close
  File "/usr/lib/python3.5/asyncio/unix_events.py", line 560, in write_eof
  File "/usr/lib/python3.5/asyncio/base_events.py", line 497, in call_soon
  File "/usr/lib/python3.5/asyncio/base_events.py", line 506, in _call_soon
  File "/usr/lib/python3.5/asyncio/base_events.py", line 334, in _check_closed
RuntimeError: Event loop is closed

我在 Ubuntu 16.04 上运行 python v3.5.2。

更新

根据 Sam 在下面的评论,我需要将我的代码更新为以下内容才能正常工作:

process = await asyncio.create_subprocess_shell(cmd1, stdin = PIPE, stdout PIPE, stderr = STDOUT)
await process.wait()

这是对他的代码的轻微修改,但有效。

【问题讨论】:

    标签: python-3.x python-asyncio


    【解决方案1】:

    问题是没有什么可以等待该过程完成;您只需等待它开始。

    async def run_async(loop = ''):
        cmd = 'sudo long_running_cmd --opt1=AAAA --opt2=BBBB'
    
        print ("[INFO] Starting script...")
        process = await asyncio.create_subprocess_shell(cmd1, stdin = PIPE, stdout = PIPE, stderr = STDOUT)
        await process.wait()
        print("[INFO] Script is complete.")
    

    【讨论】:

    • 谢谢,山姆。我不得不稍微编辑一下,但这正是我所需要的。我在上面发布了我的工作代码。谢谢!
    猜你喜欢
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 2019-01-31
    • 2018-10-10
    • 1970-01-01
    • 2020-08-23
    • 1970-01-01
    相关资源
    最近更新 更多