サブプロセス

ソースコード: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 forStreamReaderwrappers 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 forStreamReaderwrappers 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 TransportsSubprocess Protocols

定数

asyncio.subprocess.PIPE

stdin,stdout またはstderr に渡すことができます。

IfPIPE is passed tostdin argument, theProcess.stdin attributewill point to aStreamWriter instance.

IfPIPE is passed tostdout orstderr arguments, theProcess.stdout andProcess.stderrattributes 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 thecreate_subprocess_exec() andcreate_subprocess_shell()functions.

このクラスはsubprocess.Popen クラスと同様の API を持つように設計されていますが、いくつかの注意すべき違いがあります:

  • Popen と異なり、 Process インスタンスはpoll() メソッドに相当するメソッドを持っていません;

  • thecommunicate() 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)

プロセスとのやりとりを行います:

  1. stdin にデータを送信します (inputNone でない場合);

  2. EOF に達するまでstdout およびstderr からデータを読み出します;

  3. プロセスが終了するまで待ち受けます。

input オプション引数は子プロセスに送信されるデータ (bytes オブジェクト) です。

(stdout_data,stderr_data) のタプルを返します。

input を標準入力stdin nに書き込んでいる時にBrokenPipeError またはConnectionResetError 例外が送出された場合、例外は無視されます。このような条件は、全てのデータがstdin に書き込まれる前にプロセスが終了した場合に起こります。

子プロセスの標準入力stdin にデータを送りたい場合、プロセスはstdin=PIPE を設定して生成する必要があります。同様に、None 以外の何らかのデータを戻り値のタプルで受け取りたい場合、プロセスはstdout=PIPEstderr=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 sendsSIGTERM to thechild process.

On Windows the Win32 API functionTerminateProcess() iscalled to stop the child process.

kill()

子プロセスを強制終了 (kill) します。

On POSIX systems this method sendsSIGKILL to the childprocess.

Windows では、このメソッドはterminate() のエイリアスです。

stdin

Standard input stream (StreamWriter) orNoneif the process was created withstdin=None.

stdout

Standard output stream (StreamReader) orNoneif the process was created withstdout=None.

stderr

Standard error stream (StreamReader) orNoneif the process was created withstderr=None.

警告

Use thecommunicate() 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 thecreate_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 を使って書かれた同様の例 も参照してください。