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

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

サブプロセス

このセクションでは、サブプロセスを作成および管理するための高レベルの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())

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

サブプロセスの作成

重要

シェルインジェクションの脆弱性を回避するために、すべての空白文字と特殊文字が適切に引用されていることを確認するのはアプリケーションの責任です。 shlex.quote()関数を使用すると、シェルコマンドの作成に使用される文字列内の空白や特殊なシェル文字を適切にエスケープできます。


ノート

Windows でのデフォルトの非同期イベントループの実装は、サブプロセスをサポートしていません。 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のみ)によって終了したことを示します。

サブプロセスとスレッド

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

  • イベントループはメインスレッドで実行する必要があります。
  • 子ウォッチャーは、他のスレッドからサブプロセスを実行する前に、メインスレッドでインスタンス化する必要があります。 メインスレッドで get_child_watcher()関数を呼び出して、子ウォッチャーをインスタンス化します。

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

も参照してください

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

if sys.platform == "win32":
    asyncio.set_event_loop_policy(
        asyncio.WindowsProactorEventLoopPolicy())

date = asyncio.run(get_date())
print(f"Current date: {date}")

低レベルAPIを使用して記述された同じ例も参照してください。