当我必须在asyncio事件循环内运行子流程时,子流程通信挂起,整个情况都在单独的线程内。
我了解到,为了在单独的线程中运行子进程,我需要拥有
<table>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
<tr>
<td contenteditable="true">data 1</td>
<td contenteditable="true">data 2</td>
<td contenteditable="true">data 3</td>
</tr>
</table>
满足上述条件后,我完成了子流程工作。但是subprocess.communicate现在正在挂起。如果从主线程调用相同的代码,则可以正常工作。
进一步研究之后,我发现由于过程本身并没有完成,因此沟通正在暂停。 1. an event loop running in main thread, and
2. a child watcher must be initiated in main thread.
实际上正在挂起。
当我试图在子流程中发出的命令本身挂起时,我已经看到通讯挂起,但这不是这种情况。
ie await process.wait()
答案 0 :(得分:0)
看起来子进程SIGCHLD不是由工作线程而是由父线程接收的。这意味着process.wait()不会由操作系统发出信号。还有另一个discussion about this here。
儿童观察者似乎应该检测到SIGCHLD并将其传播到其他线程(或pid)及其事件循环,这似乎也是其主要设计目的。 (缺少文档,因此需要阅读源文件。)
注意:我认为t.join()阻塞了运行子观察程序的主线程 ,因此需要进行修复。我只是在其中放了一个while循环,并在t.is_alive()返回False时结束了主事件循环。
我注意到signal_noop正在射击,所以很好。该问题似乎与似乎已正确设置的 signal.set_wakeup_fd (self._csock.fileno())有关。我需要进行更多调试,以了解该事件的处理方式以及主事件循环为何未收到该信号的原因。我注意到了unix_events.py 中的 _process_self_data(自身,数据)没有发生。
Python信号处理程序始终在Python主线程中执行,即使该信号是在另一个线程中接收到的也是如此。这意味着信号不能用作线程间通信的手段。您可以改为使用来自线程模块的同步原语。
此外,只允许主线程设置新的信号处理程序。
答案 1 :(得分:0)
我认为这可以解决。对线程使用循环run_in_executor。
import asyncio
import shlex
import threading
import subprocess
import logging
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():
thread_loop = asyncio.new_event_loop()
asyncio.set_event_loop(thread_loop)
thread_loop.set_debug(True)
tasks = []
tasks.append(asyncio.ensure_future(myfunc('uname -a')))
thread_loop.run_until_complete(asyncio.gather(*tasks))
thread_loop.close()
async def myfunc3(loop=None):
await loop.run_in_executor(None, myfunc2)
def main():
logfilename='test.log'
print('Writing log to {}'.format(logfilename))
logging.basicConfig(filename=logfilename, level=logging.INFO, format='%(asctime)s %(name)s %(module)s %(levelname)-8s %(message)s')
logging.getLogger('asyncio').setLevel(logging.DEBUG)
root = logging.getLogger(__name__)
cw=asyncio.get_child_watcher()
main_loop = asyncio.get_event_loop()
main_loop.run_until_complete(asyncio.ensure_future(myfunc3(loop=main_loop)))
cw.close()
main_loop.close()
main()