HOWTO · Python
Python で Windows CMD コマンドを実行して出力を取得する方法
Python から os.system() で Windows CMD コマンドを実行するか、subprocess モジュールのパイプでコマンド出力を取得します。
このページの内容
PythonからWindows CMDコマンドを実行し、結果をコンソールに表示するだけなら os.system() を使います。戻り値はコマンドの状態を示す値であり、出力をPythonの文字列として返すものではありません。Pythonで出力を読み取る場合は、パイプと communicate() を使って subprocess モジュールで取得します。
PythonスクリプトからCMDコマンドを実行し、os.system() で出力を取得する
os.system() 関数は、コマンドをオペレーティングシステムのコマンドプロセッサに渡します。Windowsでの簡単な例は os.system("cmd /c echo hello") です。CMDが echo hello を実行し、テキストがコンソールに表示されます。この関数の戻り値が示すのはコマンドの状態であり、表示されたテキストは含まれません。
出力を人が読めればよい単純なコマンドには、この方法を使えます。ここでの例はWindows CMDの構文を使っています。dir、cd、md はCMDで使われるコマンド名で、いずれもCMDの組み込みコマンドです。cd はほかのシェルでも使われるため、これらの名前がWindowsだけに固有というわけではありません。Pythonプログラム内でコマンドの結果を使いたい場合や、標準出力と標準エラーを分けて処理したい場合は、代わりに subprocess を使います。
信頼できない入力からコマンド文字列を組み立てるのは避けてください。コマンドプロセッサはシェルのメタ文字を構文として解釈する可能性があります。os.system() を使うときは、信頼できる固定のコマンドだけを渡してください。
PythonスクリプトからCMDコマンドを実行し、subprocess モジュールで出力を取得する
subprocess.Popen() を使うと、標準出力と標準エラーに個別のパイプを設定してプロセスを開始できます。communicate() を呼び出すと、両方のストリームを読み取り、プロセスの終了を待ちます。一方のパイプがいっぱいになっている間にもう一方を読み取らないことで起こりうるデッドロックを防げます。取得した値はバイト列なので、テキストとして処理する前に、コマンドが使うエンコーディングでデコードしてください。
この単独で動作する例は、WindowsではCMDを、それ以外の環境では現在のPythonインタープリターを使います。そのため、出力を取得する方法はどちらのプラットフォームにも応用できます。取得した行を表示します。
import os
import subprocess
import sys
if os.name == "nt":
command = ["cmd", "/c", "echo", "hello"]
else:
command = [sys.executable, "-c", "print('hello')"]
process = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
stdout, stderr = process.communicate()
print(stdout.decode("utf-8").strip())
hello
Windowsでは、cmd /c はコマンドを実行してから終了します。/k はコマンドを実行した後もコマンドプロセッサを開いたままにするため、通常はスクリプトには適しません。デフォルトの shell=False では、Pythonは指定された実行ファイルを直接起動し、その引数を解析する追加のシェルは起動しません。ただし、その実行ファイルが cmd の場合、cmd はコマンドラインを解析してCMD構文を解釈します。shell=False によって信頼できない値が安全になるわけではありません。信頼できない入力をCMDのコマンドラインに入れることは絶対に避けてください。可能であれば、独立した実行ファイルを引数リストで直接呼び出す方法を優先してください。コマンドがUTF-8以外のテキストを出力する場合は、そのエンコーディングで取得したバイト列をデコードしてください。成功と失敗を区別する必要がある場合は、process.returncode を確認します。
詳しくは、Pythonの subprocess ドキュメントを参照してください。