Pythonでコマンド実行する場合はsubprocessモジュールを使う

Pythonでコマンド実行する場合はsubprocessモジュールを使う プログラミング

Pythonからコマンドを実行したい場合、subprocessを利用します。
この記事では、subprocessの使い方についてまとめています。

本記事の内容

  • subprocessとは?
  • subprocessを使ってコマンドを実行する

それでは、上記に沿って解説していきます。

subprocessとは?

最初に、subprocessについて説明します。

subprocessは、Pythonの標準ライブラリです。
つまり、別途ライブラリをインストールする必要がありません。

そして、その主な機能はサブプロセス管理になります。
サブプロセスを生成して、それをkillすることもできます。

「サブプロセス管理=コマンド実行」
上記のように考えることができます。

あと、サブプロセスの呼び出し方には2つのパターンがあります。

  • 同期
  • 非同期

subprocessでは、上記のように二つの呼び出し方が用意されています。
しかし、個人的には「同期」だけで十分と考えています。

「非同期」でサブプロセスを呼ぶ状況をあまりイメージできません。
重い処理を起動させるためのトリガーとしてなら、「非同期」を使ったことがあります。
まあ、必要となった際に覚えればよいでしょう。

以上、subprocessについての説明でした。
以降では、実際にsubprocessを利用していきましょう。

subprocessを使ってコマンドを実行する

実行するコマンドは、以下とします。

python -V

これなら、WindowsでもLinuxでもどちらでも実行可能です。
もちろん、macOSでも。

呼び出すモジュールは、以下となります。

import subprocess
from subprocess import PIPE

サブプロセスの呼び出し方は、「同期」とします。
「同期」で呼び出す場合は、run()関数を利用することになります。

run()関数には、多くのパラメータが用意されています。
今回は、よく利用するモノをピックアップしています。

  • shell
  • stdout
  • stderr
  • text

指定した方が便利なパラメータと言う方が、適切かもしれません。
では、以下で説明していきます。

shell

subprocess.run(['python', '-V'])

上記を実行すると、Pythonのバージョンが表示されます。

Python 3.9.4

でも、明らかにコマンドの書き方がオカシイと思いませんか?
shellを指定しないと、リスト形式でコマンドを書く必要があるのです。

では、shellを指定する場合を確認します。

subprocess.run('python -V', shell=True)

上記を実行すると、同じ結果が表示されます。
絶対にこっちの方が、人間に優しい書き方ですよね。

stdout

先ほどから、おかしいと思いませんか?
「print」コマンドを使っていないのに、コマンドの実行結果が表示されています。

コマンドの実行結果は、自分で表示したいです。
戻り値を変数に設定するようにしてみます。

sub_proc = subprocess.run('python -V', shell=True)
print("-----")
print(sub_proc)

上記を実行すると、以下の結果となります。

Python 3.9.4
-----
CompletedProcess(args='python -V', returncode=0)

どうもまだおかしいです。
コマンド実行結果が、勝手に表示されています。
それにsub_procにコマンド実行結果が格納されていません。

stdoutを指定すれば、sub_procにコマンド実行結果が格納されます。

sub_proc = subprocess.run('python -V', shell=True, stdout=PIPE)
print("-----")
print(sub_proc)

実行結果は、以下。

-----
CompletedProcess(args='python -V', returncode=0, stdout=b'Python 3.9.4\r\n')

同時に、勝手にコマンド実行結果が表示されなくなりました。
sub_procの中のstdoutに結果が入っています。

stderr

stdoutのエラー版です。

sub_proc = subprocess.run('python -W', shell=True, stdout=PIPE)
print("-----")
print(sub_proc)

上記を実行すると、次のように表示されます。

Argument expected for the -W option
usage: python.exe [option] ... [-c cmd | -m mod | file | -] [arg] ...
Try `python -h' for more information.
-----
CompletedProcess(args='python -W', returncode=2, stdout=b'')

「-W」なんてオプションはないというエラーですね。
このエラーが勝手に表示されています。

stdoutと同じように設定します。

sub_proc = subprocess.run('python -W', shell=True, stdout=PIPE, stderr=PIPE)
print("-----")
print(sub_proc)

実行結果は、以下。

-----
CompletedProcess(args='python -W', returncode=2, stdout=b'', stderr=b"Argument expected for the -W option\r\nusage: python.exe [option] ... [-c cmd | -m mod | file | -] [arg] ...\r\nTry `python -h' for more information.\r\n")

sub_procの中のstderrに結果が入っています。

text

stdout・stderrを設定すると、sub_procの中にコマンド実行結果を格納できました。
ただ、その際に「b」と付いているのに気が付きましたか?

stdout=b'Python 3.9.4\r\n'

これは、byte列型を表しています。
byte列型が安全なのはわかりますが、少し扱いにくいです。

それを文字列にしたい場合は、textを設定します。

sub_proc = subprocess.run('python -V', shell=True, stdout=PIPE, stderr=PIPE, text=True)
print("-----")
print(sub_proc)

実行結果は、以下。

-----
CompletedProcess(args='python -V', returncode=0, stdout='Python 3.9.4\n', stderr='')

「b」が消えて、単なる文字列になりました。

stdout='Python 3.9.4\n'

まとめ

上記のパラメータを利用すれば、ほぼやりたいことはできるでしょう。
Pythonからコマンドを実行して、その結果を利用してということを。

最後に、戻り値(sub_proc)の中の「returncode」について説明しておきましょう。

returncodeが「0」なら、正常にコマンドが実行されたということです。
「0」以外は、正常ではないと考えてよいでしょう。

「python -W」を実行した際は、returncodeは「2」となっています。
よって、returncodeをもとにコマンド実行の結果を判断するとことになります。

タイトルとURLをコピーしました