サブプロセス—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.9/library/asyncio-subprocess
移動先:案内検索

サブプロセス

ソースコード: :source: `Lib / asyncio / subprocess.py`, :source: `Lib / asyncio / base_subprocess.py`



このセクションでは、サブプロセスを作成および管理するための高レベルのasync / await asyncioAPIについて説明します。

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

サブセクションも参照してください。

サブプロセスの作成

ノート

ProactorEventLoop が使用されている場合、Windowsではサブプロセスを使用できます。 詳細については、 Windowsでのサブプロセスサポートを参照してください。


も参照してください

asyncioには、サブプロセスを操作するための低レベル APIもあります:loop.subprocess_exec()loop.subprocess_shell()loop.connect_read_pipe()loop.connect_write_pipe() サブプロセストランスポートおよびサブプロセスプロトコルとして。


定数

asyncio.subprocess.PIPE

stdinstdout 、または stderr パラメーターに渡すことができます。

PIPEstdin 引数に渡された場合、 Process.stdin 属性は StreamWriter インスタンスを指します。

PIPEstdout または stderr 引数に渡されると、 Process.stdout および Process.stderr 属性は StreamReader インスタンスをポイントします。

asyncio.subprocess.STDOUT
stderr 引数として使用でき、標準エラーを標準出力にリダイレクトする必要があることを示す特別な値。
asyncio.subprocess.DEVNULL
プロセス作成関数の stdinstdout 、または stderr 引数として使用できる特別な値。 これは、特別なファイル os.devnull が対応するサブプロセスストリームに使用されることを示しています。


サブプロセスとの相互作用

create_subprocess_exec()関数とcreate_subprocess_shell()関数はどちらも、 Process クラスのインスタンスを返します。 Process は、サブプロセスとの通信とその完了の監視を可能にする高レベルのラッパーです。

class asyncio.subprocess.Process

create_subprocess_exec()およびcreate_subprocess_shell()関数によって作成されたOSプロセスをラップするオブジェクト。

このクラスは、 subprocess.Popen クラスと同様のAPIを持つように設計されていますが、いくつかの顕著な違いがあります。

  • Popenとは異なり、Processインスタンスには poll()メソッドに相当するものがありません。

  • communicate()およびwait()メソッドには timeout パラメーターがありません。wait_for()関数を使用してください。

  • Process.wait()メソッドは非同期ですが、 subprocess.Popen.wait()メソッドはブロッキングビジーループとして実装されています。

  • Universal_newlines パラメーターはサポートされていません。

このクラスはスレッドセーフではありません

サブプロセスとスレッドセクションも参照してください。

send_signal(signal)

シグナル signal を子プロセスに送信します。

ノート

Windowsでは、SIGTERMterminate()のエイリアスです。 CTRL_C_EVENTおよびCTRL_BREAK_EVENTは、CREATE_NEW_PROCESS_GROUPを含む creationflags パラメーターで開始されたプロセスに送信できます。

terminate()

子プロセスを停止します。

POSIXシステムでは、このメソッドは signal.SIGTERM を子プロセスに送信します。

Windowsでは、Win32API関数TerminateProcess()が呼び出されて、子プロセスが停止します。

kill()

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

POSIXシステムでは、このメソッドはSIGKILLを子プロセスに送信します。

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

stdin

プロセスがstdin=Noneで作成された場合は、標準入力ストリーム( StreamWriter )またはNone

stdout

プロセスがstdout=Noneで作成された場合は、標準出力ストリーム( StreamReader )またはNone

stderr

プロセスがstderr=Noneで作成された場合は、標準エラーストリーム( StreamReader )またはNone

警告

process.stdin.write()await process.stdout.read()、または await process.stderr.read [ではなく、communicate()メソッドを使用してください。 X138X]。 これにより、ストリームが読み取りまたは書き込みを一時停止し、子プロセスをブロックすることによるデッドロックが回避されます。

pid

プロセス識別番号(PID)。

create_subprocess_shell()関数によって作成されたプロセスの場合、この属性は生成されたシェルのPIDであることに注意してください。

returncode

プロセスが終了したときの戻りコード。

None値は、プロセスがまだ終了していないことを示します。

負の値-Nは、子がシグナルN(POSIXのみ)によって終了したことを示します。

サブプロセスとスレッド

標準の非同期イベントループは、デフォルトで異なるスレッドからのサブプロセスの実行をサポートします。

Windowsでは、サブプロセスは ProactorEventLoop によってのみ提供され(デフォルト)、 SelectorEventLoop はサブプロセスをサポートしていません。

UNIXでは、子ウォッチャーがサブプロセスの終了待機に使用されます。詳細については、プロセスウォッチャーを参照してください。

バージョン3.8で変更: UNIXは、 ThreadedChildWatcher を使用して、制限なしに異なるスレッドからサブプロセスを生成するように切り替えました。

非アクティブの現在の子ウォッチャーでサブプロセスを生成すると、 RuntimeError が発生します。


代替のイベントループの実装には独自の制限がある場合があることに注意してください。 それらのドキュメントを参照してください。

も参照してください

asyncio セクションの同時実行性とマルチスレッド。


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を使用して記述された同じ例も参照してください。