サブプロセス¶
ソースコード: Lib/asyncio/subprocess.py, Lib/asyncio/base_subprocess.py
このセクションはサブプロセスの生成と管理を行う高水準の async/await asyncio API について説明します。
以下は、 asyncio モジュールがどのようにシェルコマンドを実行し、結果を取得できるかを示す例です:
import asyncio
async def run(cmd):
proc = await asyncio.create_subprocess_shell(
cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
stdout, stderr = await proc.communicate()
print(f'[{cmd!r} exited with {proc.returncode}]')
if stdout:
print(f'[stdout]\n{stdout.decode()}')
if stderr:
print(f'[stderr]\n{stderr.decode()}')
asyncio.run(run('ls /zzz'))
このサンプルコードは以下を出力します:
['ls /zzz' exited with 1]
[stderr]
ls: /zzz: No such file or directory
全ての asyncio のサブプロセス関数は非同期ですが、 asyncio モジュールはこれらの非同期関数と協調するための多くのツールを提供しているので、複数のサブプロセスを並列に実行して監視することは簡単です。実際、上記のサンプルコードを複数のコマンドを同時に実行するように修正するのはきわめて単純です:
async def main():
await asyncio.gather(
run('ls /zzz'),
run('sleep 1; echo "hello"'))
asyncio.run(main())
使用例 節も参照してください。
サブプロセスの生成¶
- async asyncio.create_subprocess_exec(program, *args, stdin=None, stdout=None, stderr=None, limit=None, **kwds)¶
サブプロセスを作成します。
The limit argument sets the buffer limit for
StreamReader
wrappers forstdout
andstderr
(ifsubprocess.PIPE
is passed to stdout and stderr arguments).Process
のインスタンスを返します。他のパラメータについては
loop.subprocess_exec()
を参照してください。バージョン 3.10 で変更: loop パラメータが削除されました。
- async asyncio.create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, limit=None, **kwds)¶
シェルコマンド cmd を実行します。
The limit argument sets the buffer limit for
StreamReader
wrappers forstdout
andstderr
(ifsubprocess.PIPE
is passed to stdout and stderr 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 に渡すことができます。
If PIPE is passed to stdin argument, the
Process.stdin
attribute will point to aStreamWriter
instance.If PIPE is passed to stdout or stderr 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 クラスはサブプロセスと通信したり、サブプロセスの完了を監視したりするための高水準のラッパーです。
- class asyncio.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 a timeout parameter: use thewait_for()
function;subprocess.Popen.wait()
メソッドが同期処理のビジーループとして実装されているのに対して、Process.wait()
メソッドは非同期処理です;universal_newlines パラメータはサポートされていません。
このクラスは スレッド安全ではありません。
サブプロセスとスレッド 節も参照してください。
- async wait()¶
子プロセスが終了するのを待ち受けます。
returncode
属性を設定し、その値を返します。注釈
stdout=PIPE
またはstderr=PIPE
を使っており、OS パイプバッファがさらなるデータを受け付けるようになるまで子プロセスをブロックするほど大量の出力を生成場合、このメソッドはデッドロックする可能性があります。この条件を避けるため、パイプを使用する場合はcommunicate()
メソッドを使ってください。
- async communicate(input=None)¶
プロセスとのやりとりを行います:
stdin にデータを送信します (input が
None
でない場合);stdin を閉じます;
EOF に達するまで stdout および stderr からデータを読み出します;
プロセスが終了するまで待ち受けます。
input オプション引数は子プロセスに送信されるデータ (
bytes
オブジェクト) です。(stdout_data, stderr_data)
のタプルを返します。input を標準入力 stdin nに書き込んでいる時に
BrokenPipeError
またはConnectionResetError
例外が送出された場合、例外は無視されます。このような条件は、全てのデータが stdin に書き込まれる前にプロセスが終了した場合に起こります。子プロセスの標準入力 stdin にデータを送りたい場合、プロセスは
stdin=PIPE
を設定して生成する必要があります。同様に、None
以外の何らかのデータを戻り値のタプルで受け取りたい場合、プロセスはstdout=PIPE
とstderr=PIPE
のいずれかまたは両方を指定して生成しなければなりません。プロセスから受信したデータはメモリ上にバッファーされることに注意してください。そのため、返されるデータのサイズが大きいかまたは無制限の場合はこのメソッドを使わないようにしてください。
バージョン 3.12 で変更: stdin gets closed when
input=None
too.
- send_signal(signal)¶
子プロセスにシグナル signal を送信します。
注釈
On Windows,
SIGTERM
is an alias forterminate()
.CTRL_C_EVENT
andCTRL_BREAK_EVENT
can be sent to processes started with a creationflags parameter which includesCREATE_NEW_PROCESS_GROUP
.
- terminate()¶
子プロセスを停止します。
On POSIX systems this method sends
SIGTERM
to the child process.On Windows the Win32 API function
TerminateProcess()
is called to stop the child process.
- kill()¶
子プロセスを強制終了 (kill) します。
On POSIX systems this method sends
SIGKILL
to the child process.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()
,await process.stdout.read()
orawait process.stderr.read()
. This avoids deadlocks due to streams pausing reading or writing and 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
はサブプロセスをサポートしていません。
UNIX の child watchers はサブプロセスの終了を待ち受けるために使われます。より詳しい情報については プロセスのウオッチャー を参照してください。
バージョン 3.8 で変更: UNIX では、異なるスレッドから何らの制限なくサブプロセスを生成するために ThreadedChildWatcher
を使うようになりました。
現在の子プロセスのウオッチャーが アクティブでない 場合にサブプロセスを生成すると RuntimeError
例外が送出されます。
標準で提供されない別のイベントループ実装の場合、固有の制限がある可能性があります; それぞれの実装のドキュメントを参照してください。
使用例¶
サブプロセスの制御のために Process
クラスを使い、サブプロセスの標準出力を読み出すために StreamReader
を使う例です。
サブプロセスは create_subprocess_exec()
関数により生成されます:
import asyncio
import sys
async def get_date():
code = 'import datetime; print(datetime.datetime.now())'
# Create the subprocess; redirect the standard output
# into a pipe.
proc = await asyncio.create_subprocess_exec(
sys.executable, '-c', code,
stdout=asyncio.subprocess.PIPE)
# Read one line of output.
data = await proc.stdout.readline()
line = data.decode('ascii').rstrip()
# Wait for the subprocess exit.
await proc.wait()
return line
date = asyncio.run(get_date())
print(f"Current date: {date}")
低水準の API を使って書かれた 同様の例 も参照してください。