使用await nursery.start(trio.run_process)生成进程的正确语法及报错解决
问题解决
错误原因
你把trio.run_process的stdin=PIPE参数直接传给了Nursery.start(),但start()方法本身只接受name和task_status这两个关键字参数,因此触发了TypeError。
另外要注意:trio.run_process是高层API,它会自动等待进程执行完毕并返回CompletedProcess对象,无法获取运行中的进程实例来调用terminate()这类方法——这和你想要“获取process-object进行后续处理”的需求不匹配。
正确解决方案
要获取可操作的运行中进程对象,应该使用trio.Process类(类似subprocess.Popen的异步版本),代码修改如下:
import trio from subprocess import PIPE VAR = {'prg': None} async def main(): async with trio.open_nursery() as nrs: # 创建trio.Process对象,配置参数 VAR['prg'] = trio.Process('cvlc -'.split(), stdin=PIPE) # 启动进程 await VAR['prg'].start() # 启动测试任务 nrs.start_soon(test) async def test(): while VAR['prg'] is None: await trio.sleep(0.1) print(dir(VAR['prg'])) print(type(VAR['prg'].stdin)) await trio.sleep(2) # 终止进程 VAR['prg'].terminate() # 等待进程完全结束,避免僵尸进程 await VAR['prg'].wait() if __name__ == '__main__': trio.run(main)
如果你坚持要用trio.run_process(仅适用于不需要中途操作进程的场景),需要用lambda包裹调用,把参数传递给run_process而不是start():
async def main(): async with trio.open_nursery() as nrs: # 用lambda包裹run_process的调用,正确传递参数 VAR['prg'] = await nrs.start(lambda: trio.run_process('cvlc -'.split(), stdin=PIPE)) nrs.start_soon(test)
但注意这种情况下,VAR['prg']是进程结束后的CompletedProcess对象,调用terminate()会报错,因为进程已经不存在了。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

