Windows 上の Python 3.4 では、子プロセスによって stdout/stderr に書き込まれたデータをストリーミングする必要があります。つまり、Python 3.4 で導入されたasyncioフレームワークを使用して、発生した出力を受け取ります。その後、プログラムの終了コードも特定する必要があります。これどうやってするの?
3307 次
4 に答える
8
これまでに思いついたソリューションでは、SubprocessProtocolを使用して子プロセスから出力を受け取り、関連するトランスポートを使用してプロセスの終了コードを取得します。これが最適かどうかはわかりませんが。JF Sebastian による同様の質問への回答に基づいてアプローチしました。
import asyncio
import contextlib
import os
import locale
class SubprocessProtocol(asyncio.SubprocessProtocol):
def pipe_data_received(self, fd, data):
if fd == 1:
name = 'stdout'
elif fd == 2:
name = 'stderr'
text = data.decode(locale.getpreferredencoding(False))
print('Received from {}: {}'.format(name, text.strip()))
def process_exited(self):
loop.stop()
if os.name == 'nt':
# On Windows, the ProactorEventLoop is necessary to listen on pipes
loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
else:
loop = asyncio.get_event_loop()
with contextlib.closing(loop):
# This will only connect to the process
transport = loop.run_until_complete(loop.subprocess_exec(
SubprocessProtocol, 'python', '-c', 'print(\'Hello async world!\')'))[0]
# Wait until process has finished
loop.run_forever()
print('Program exited with: {}'.format(transport.get_returncode()))
于 2014-06-26T16:43:42.367 に答える
1
イベント ループは、stdout/stderr の残りのデータを読み取る前に、プロセスの終了を確認して通知する場合があるため、プロセスの終了イベントに加えて、PIPE の終了イベントを確認する必要があります。
これは、aknuds1 の回答の修正です。
class SubprocessProtocol(asyncio.SubprocessProtocol):
def __init__(self):
self._exited = False
self._closed_stdout = False
self._closed_stderr = False
@property
def finished(self):
return self._exited and self._closed_stdout and self._closed_stderr
def signal_exit(self):
if not self.finished:
return
loop.stop()
def pipe_data_received(self, fd, data):
if fd == 1:
name = 'stdout'
elif fd == 2:
name = 'stderr'
text = data.decode(locale.getpreferredencoding(False))
print('Received from {}: {}'.format(name, text.strip()))
def pipe_connection_lost(self, fd, exc):
if fd == 1:
self._closed_stdout = True
elif fd == 2:
self._closed_stderr = True
self.signal_exit()
def process_exited(self):
self._exited = True
self.signal_exit()
于 2015-05-19T13:13:19.727 に答える