なんだかGoodVibes

日々の勉強メモです。

【Python】subprocess.Popenを使用してコマンドを実行する

こんにちは。
本日はPythonメモです。

概要

subprocessモジュールは標準ライブラリです。
このモジュールを使用することで
外部コマンドやプログラムを実行することができます。

以下の記事もsubprocessモジュールを使用しているので
ご参考までに。

nandakagoodvibes.hatenablog.com

本記事では、以下のディレクトリ構成を準備して試します。

tmp
└ hoge.txt


サンプルコード

引数に指定したコマンドを非同期で実行します。
戻り値は、Popenオブジェクトです。

import subprocess

result = subprocess.Popen(['ls', './tmp'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Popenは非同期のため、完了を待機する必要がある場合があります。
待機の方法はいくつかあります。

wait()で待機

wait()は指定したプロセスが終了するまでブロックし
終了コードを返します。

import subprocess

result = subprocess.Popen(['ls', './tmp'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(result)

returncode = result.wait(timeout=5)
print()
print(result)
print(f'args = {result.args}')
print(f'returncode = {result.returncode}')

実行結果は以下です。

<Popen: returncode: None args: ['ls', './tmp']>

<Popen: returncode: 0 args: ['ls', './tmp']>
args = ['ls', './tmp']
returncode = 0


communicate()で待機

communicate()は指定したプロセスが終了するまでブロックし
標準出力と標準エラー出力を読み取ります。

import subprocess

result = subprocess.Popen(['ls', './tmp'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(result)

stdout, stderr = result.communicate(timeout=5)
print()
print(result)
print(f'args = {result.args}')
print(f'stdout = {stdout.decode().strip()}')
print(f'stderr = {stderr.decode().strip()}')
print(f'returncode = {result.returncode}')

実行結果は以下です。

<Popen: returncode: None args: ['ls', './tmp']>

<Popen: returncode: 0 args: ['ls', './tmp']>
args = ['ls', './tmp']
stdout = hoge.txt
stderr = 
returncode = 0


poll()で待機

poll()はプロセスが終了していない場合はNoneを返します。
これを利用して、Noneでなくなるまでループして待機します。

result = subprocess.Popen(['ls', './tmp'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while result.poll() is None:
    print(result)
    time.sleep(0.1)

print()
print(result)
print(f'poll() = {result.poll()}')
print(f'args = {result.args}')
print(f'returncode = {result.returncode}')

実行結果は以下です。

<Popen: returncode: None args: ['ls', './tmp']>

<Popen: returncode: 0 args: ['ls', './tmp']>
poll() = 0
args = ['ls', './tmp']
returncode = 0



以上です。