[Python] コマンドを実行して結果を取得する方法

[Python] コマンドを実行して結果を取得する方法

Python から コマンドを実行する方法

Python から コマンドを実行する方法をまとめます。

subprocess で別のプロセスとして任意のコマンドを起動することが可能です。

subprocess — サブプロセス管理 — Python 3.7.4 ドキュメント

以下、Windows環境で試しているので mac, linux の人はコマンドをいい感じに変えて試してください。

単純な例

例えばメモ帳を Python から起動するには以下のように記述します。

import subprocess

subprocess.Popen("notepad")

subprocess.Popen() は引数にコマンドを受け取り、それを実行します。

Windows に組み込まれたコマンドを実行

Windows にあらかじめ組み込まれているコマンド(startdir 等)は上記の方法ではうまく実行できません。

FileNotFoundError: [WinError 2] 指定されたファイルが見つかりません。

上記のように「指定されたファイルが見つかりません。」とエラーになります。これを解消するにはコマンドをコマンドプロンプトから実行する必要があります。

import subprocess

subprocess.Popen("start C:\\",  shell=True)

shell=True のパラメータでシェル上(コマンドプロンプト)でコマンドを実行できるように設定しています。

上のコマンドはエクスプローラーでCドライブ直下を起動する例です。shell=True がなければエラーで失敗します。

セキュリティで考慮すべき点

subprocess — サブプロセス管理 — Python 3.7.4 ドキュメント

シェルに渡すコマンドにメタ文字が含まれていたりするまずいので、適切なエスケープを行うのがアプリケーション側には求められるようです。

shlex — 単純な字句解析 — Python 3.7.4 ドキュメント

シェルコマンドで使用される文字列の空白やメタ文字は shlex.quote() 関数を使うと正しくエスケープできます。上のページを参考にしていい感じに処理してください。

実行結果を文字列で受け取る

subprocess — サブプロセス管理 — Python 3.7.4 ドキュメント

コマンドの実行結果がコマンドライン上に文字列で表示されるようなものがあります。この結果の文字列を取得するには、subprocess.check_output() を使います。

バッチコマンドでシリアル番号やPCモデル、CUPの型番、OS情報を取得する方法 │ Web備忘録

以前上の記事で紹介した、WindowsPCのハードウェア情報を取得するコマンドですが、この取得結果を Python 上で取得するには次のようにします。

import subprocess

# CPU名を取得する
cpuResult = subprocess.check_output('wmic CPU get Name', stdin=DEVNULL, stderr=DEVNULL, shell=True)
cpu = str(cpuResult)

check_output は戻り値で出力された文字列を バイト列 として返します。したがって文字列として扱いたい場合は変換をかましましょう。

subprocess.run() を使う

調べていると、subprocess.check_output() は古い関数であることがわかりました。

Python 3.5 より前のバージョンでは、サブプロセスに対して以下の 3 つの関数からなる高水準 API が用意されていました。現在多くの場合 run() の使用で済みますが、既存の多くのコードではこれらの関数が使用されています。

subprocess.call(args, , stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None)
subprocess.check_call(args,
, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None)
?
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, cwd=None, encoding=None, errors=None, universal_newlines=None, timeout=None, text=None)

Python 3.5 より大きなバージョンだと、subprocess.run() で代用できるみたいなのでその方法も載せておきます。

import subprocess

completedProcess = subprocess.run(['wmic', 'CPU', 'get', 'Name'], check=True, shell=True, stdout=subprocess.PIPE)
print(completedProcess.stdout)

引数で指定するコマンドをパラメータごとに分割してリストで渡すようにします。あとは check, shell, stdout でそれぞれパラ値を指定してやると、プロセスの実行結果を戻り値で取得できます。

subprocess.check_output() と異なり、結果は CompletedProcess という型になります。CompletedProcess には stdout に実行結果の出力が入っています。バイト列なのでいい感じに処理してください。

CompletedProcess(args=['wmic', 'CPU', 'get', 'Name'], returncode=0, stdout=b'Name                                     \r\r\nIntel(R) Core(TM) i5-4570 CPU @ 3.20GHz  \r\r\n\r\r\n')

結果は上のような感じです。

以上。

参考URL

Pythonカテゴリの最新記事