gpt4 book ai didi

python - 为什么在不同线程中调用 asyncio subprocess.communicate 会挂起?

转载 作者:太空宇宙 更新时间:2023-11-04 00:06:37 24 4
gpt4 key购买 nike

当我必须在 asyncio 事件循环中运行子进程时,我遇到了子进程通信挂起的情况,并且整个事情都在一个单独的线程中。

我了解到,为了在单独的线程中运行子进程,我需要有

1. an event loop running in main thread, and
2. a child watcher must be initiated in main thread.

在具备上述条件后,我的子流程开始工作了。但是 subprocess.communicate 现在挂了。如果从主线程调用它,相同的代码将起作用。

进一步挖掘后,我观察到通信挂起,因为进程没有自行完成。 即await process.wait()其实是挂了。

我已经看到当我试图在子进程中发出的命令本身挂起时通信挂起,但这里不是这种情况。

import asyncio
import shlex
import threading
import subprocess
async def sendcmd(cmd):
cmdseq = tuple(shlex.split(cmd))
print(cmd)
p = await asyncio.create_subprocess_exec(*cmdseq, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(p.pid)
output = (await asyncio.wait_for(p.communicate(), 5))[0]
output = output.decode('utf8')
print(output)
return output


async def myfunc(cmd):
o = await sendcmd(cmd)
return o

def myfunc2():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
tasks = []
tasks.append(asyncio.ensure_future(myfunc('uname -a')))
loop.run_until_complete(asyncio.gather(*tasks))

async def myfunc3():
t = threading.Thread(target=myfunc2)
t.start()
t.join()

def main():
asyncio.get_child_watcher()
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.ensure_future(myfunc3()))
loop.close()

main()

最佳答案

看起来子进程 SIGCHLD 不是由工作线程接收的,而是由父线程接收的。这意味着 process.wait() 不会被操作系统发出信号。还有一个discussion about this here .

看起来子观察者应该检测 SIGCHLD 并将其传播到其他线程(或 pids)及其事件循环,这似乎也是它的主要设计目的。 (缺少文档,因此需要阅读源代码。)

注意:我认为 t.join() 阻塞了运行子监视器的主线程,因此需要修复。我只是在那里放了一个 while 循环,并在 t.is_alive() 返回 False 时结束主事件循环。

我注意到 signal_noop正在开火,所以很好。该问题似乎与 signal.set_wakeup_fd(self._csock.fileno()) 相关,似乎设置正确。我需要进行更多调试以了解该事件的处理方式以及主事件循环未收到该信号的原因。我注意到 unix_events.py 中的 _process_self_data(self, data) 没有发生。

Signals and threads

Python 信号处理程序始终在主 Python 线程中执行,即使信号是在另一个线程中接收到的。这意味着信号不能用作线程间通信的手段。您可以改用线程模块中的同步原语。

此外,只允许主线程设置新的信号处理程序。

关于python - 为什么在不同线程中调用 asyncio subprocess.communicate 会挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53883001/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com