サブプロセス¶
ソースコード:Lib/asyncio/subprocess.py,Lib/asyncio/base_subprocess.py
このセクションはサブプロセスの生成と管理を行う高水準の async/await asyncio API について説明します。
以下は、 asyncio モジュールがどのようにシェルコマンドを実行し、結果を取得できるかを示す例です:
importasyncioasyncdefrun(cmd):proc=awaitasyncio.create_subprocess_shell(cmd,stdout=asyncio.subprocess.PIPE,stderr=asyncio.subprocess.PIPE)stdout,stderr=awaitproc.communicate()print(f'[{cmd!r} exited with{proc.returncode}]')ifstdout:print(f'[stdout]\n{stdout.decode()}')ifstderr:print(f'[stderr]\n{stderr.decode()}')asyncio.run(run('ls /zzz'))
このサンプルコードは以下を出力します:
['ls /zzz'exitedwith1][stderr]ls:/zzz:Nosuchfileordirectory
全ての asyncio のサブプロセス関数は非同期ですが、 asyncio モジュールはこれらの非同期関数と協調するための多くのツールを提供しているので、複数のサブプロセスを並列に実行して監視することは簡単です。実際、上記のサンプルコードを複数のコマンドを同時に実行するように修正するのはきわめて単純です:
asyncdefmain():awaitasyncio.gather(run('ls /zzz'),run('sleep 1; echo "hello"'))asyncio.run(main())
使用例 節も参照してください。
サブプロセスの生成¶
- coroutineasyncio.create_subprocess_exec(program,*args,stdin=None,stdout=None,stderr=None,limit=None,**kwds)¶
サブプロセスを作成します。
Thelimit argument sets the buffer limit for
StreamReader
wrappers forProcess.stdout
andProcess.stderr
(ifsubprocess.PIPE
is passed tostdout andstderr arguments).Process
のインスタンスを返します。他のパラメータについては
loop.subprocess_exec()
を参照してください。バージョン 3.10 で変更:loop パラメータが削除されました。
- coroutineasyncio.create_subprocess_shell(cmd,stdin=None,stdout=None,stderr=None,limit=None,**kwds)¶
シェルコマンドcmd を実行します。
Thelimit argument sets the buffer limit for
StreamReader
wrappers forProcess.stdout
andProcess.stderr
(ifsubprocess.PIPE
is passed tostdout andstderr arguments).Process
のインスタンスを返します。他のパラメータについては
loop.subprocess_shell()
のドキュメントを参照してください。重要
シェルインジェクション の脆弱性を回避するために全ての空白文字および特殊文字を適切にクオートすることは、アプリケーション側の責任で確実に行ってください。シェルコマンドを構成する文字列内の空白文字と特殊文字のエスケープは、
shlex.quote()
関数を使うと適切に行うことができます。バージョン 3.10 で変更:loop パラメータが削除されました。
注釈
サブプロセスは、ProactorEventLoop
を使えば Windows でも利用可能です。詳しくはWindows におけるサブプロセスのサポート を参照してください。
参考
asyncio は以下に挙げるサブプロセスと協調するための低水準の API も持っています:loop.subprocess_exec()
,loop.subprocess_shell()
,loop.connect_read_pipe()
,loop.connect_write_pipe()
およびSubprocess Transports とSubprocess Protocols。
定数¶
- asyncio.subprocess.PIPE¶
stdin,stdout またはstderr に渡すことができます。
IfPIPE is passed tostdin argument, the
Process.stdin
attributewill point to aStreamWriter
instance.IfPIPE is passed tostdout orstderr arguments, the
Process.stdout
andProcess.stderr
attributes will point toStreamReader
instances.
- asyncio.subprocess.STDOUT¶
stderr 引数に対して利用できる特殊な値で、標準エラー出力が標準出力にリダイレクトされることを意味します。
- asyncio.subprocess.DEVNULL¶
プロセスを生成する関数のstdin,stdout またはstderr 引数に利用できる特殊な値です。対応するサブプロセスのストリームに特殊なファイル
os.devnull
が使われることを意味します。
サブプロセスとやりとりする¶
create_subprocess_exec()
とcreate_subprocess_shell()
の2つの関数はどちらもProcess クラスのインスタンスを返します。Process クラスはサブプロセスと通信したり、サブプロセスの完了を監視したりするための高水準のラッパーです。
- classasyncio.subprocess.Process¶
An object that wraps OS processes created by the
create_subprocess_exec()
andcreate_subprocess_shell()
functions.このクラスは
subprocess.Popen
クラスと同様の API を持つように設計されていますが、いくつかの注意すべき違いがあります:Popen と異なり、 Process インスタンスは
poll()
メソッドに相当するメソッドを持っていません;the
communicate()
andwait()
methods don't have atimeout parameter: use thewait_for()
function;subprocess.Popen.wait()
メソッドが同期処理のビジーループとして実装されているのに対して、Process.wait()
メソッドは非同期処理です;universal_newlines パラメータはサポートされていません。
このクラスはスレッド安全ではありません。
サブプロセスとスレッド 節も参照してください。
- coroutinewait()¶
子プロセスが終了するのを待ち受けます。
returncode
属性を設定し、その値を返します。注釈
stdout=PIPE
またはstderr=PIPE
を使っており、OS パイプバッファがさらなるデータを受け付けるようになるまで子プロセスをブロックするほど大量の出力を生成場合、このメソッドはデッドロックする可能性があります。この条件を避けるため、パイプを使用する場合はcommunicate()
メソッドを使ってください。
- coroutinecommunicate(input=None)¶
プロセスとのやりとりを行います:
stdin にデータを送信します (input が
None
でない場合);EOF に達するまでstdout およびstderr からデータを読み出します;
プロセスが終了するまで待ち受けます。
input オプション引数は子プロセスに送信されるデータ (
bytes
オブジェクト) です。(stdout_data,stderr_data)
のタプルを返します。input を標準入力stdin nに書き込んでいる時に
BrokenPipeError
またはConnectionResetError
例外が送出された場合、例外は無視されます。このような条件は、全てのデータがstdin に書き込まれる前にプロセスが終了した場合に起こります。子プロセスの標準入力stdin にデータを送りたい場合、プロセスは
stdin=PIPE
を設定して生成する必要があります。同様に、None
以外の何らかのデータを戻り値のタプルで受け取りたい場合、プロセスはstdout=PIPE
とstderr=PIPE
のいずれかまたは両方を指定して生成しなければなりません。プロセスから受信したデータはメモリ上にバッファーされることに注意してください。そのため、返されるデータのサイズが大きいかまたは無制限の場合はこのメソッドを使わないようにしてください。
- send_signal(signal)¶
子プロセスにシグナルsignal を送信します。
注釈
On Windows,
SIGTERM
is an alias forterminate()
.CTRL_C_EVENT
andCTRL_BREAK_EVENT
can be sent to processesstarted with acreationflags parameter which includesCREATE_NEW_PROCESS_GROUP
.
- terminate()¶
子プロセスを停止します。
On POSIX systems this method sends
SIGTERM
to thechild process.On Windows the Win32 API function
TerminateProcess()
iscalled to stop the child process.
- kill()¶
子プロセスを強制終了 (kill) します。
On POSIX systems this method sends
SIGKILL
to the childprocess.Windows では、このメソッドは
terminate()
のエイリアスです。
- stdin¶
Standard input stream (
StreamWriter
) orNone
if the process was created withstdin=None
.
- stdout¶
Standard output stream (
StreamReader
) orNone
if the process was created withstdout=None
.
- stderr¶
Standard error stream (
StreamReader
) orNone
if the process was created withstderr=None
.
警告
Use the
communicate()
method rather thanprocess.stdin.write()
,awaitprocess.stdout.read()
orawaitprocess.stderr.read()
.This avoids deadlocks due to streams pausing reading or writingand blocking the child process.- pid¶
子プロセスのプロセス番号 (PID) です。
Note that for processes created by the
create_subprocess_shell()
function, this attribute is the PID of the spawned shell.
- returncode¶
プロセスが終了した時の終了ステータスを返します。
この属性が
None
であることは、プロセスがまだ終了していないことを示しています。負の値
-N
は子プロセスがシグナルN
により中止させられたことを示します (POSIX のみ)。
サブプロセスとスレッド¶
標準的な asyncio のイベントループは、異なるスレッドからサブプロセスを実行するのをデフォルトでサポートしています。
Windows のサブプロセスはProactorEventLoop
(デフォルト) のみ提供され、SelectorEventLoop
はサブプロセスをサポートしていません。
On UNIXchild watchers are used for subprocess finish waiting, seeProcess Watchers for more info.
バージョン 3.8 で変更:UNIX switched to useThreadedChildWatcher
for spawning subprocesses fromdifferent threads without any limitation.
Spawning a subprocess withinactive current child watcher raisesRuntimeError
.
標準で提供されない別のイベントループ実装の場合、固有の制限がある可能性があります; それぞれの実装のドキュメントを参照してください。
使用例¶
サブプロセスの制御のためにProcess
クラスを使い、サブプロセスの標準出力を読み出すためにStreamReader
を使う例です。
サブプロセスはcreate_subprocess_exec()
関数により生成されます:
importasyncioimportsysasyncdefget_date():code='import datetime; print(datetime.datetime.now())'# Create the subprocess; redirect the standard output# into a pipe.proc=awaitasyncio.create_subprocess_exec(sys.executable,'-c',code,stdout=asyncio.subprocess.PIPE)# Read one line of output.data=awaitproc.stdout.readline()line=data.decode('ascii').rstrip()# Wait for the subprocess exit.awaitproc.wait()returnlinedate=asyncio.run(get_date())print(f"Current date:{date}")
低水準の API を使って書かれた同様の例 も参照してください。