Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

【Python入門】PythonからWindowsのコマンドプロンプトを使えるsubprocessモジュールの説明

PythonでWindowsコマンドプロンプトを実行できるsubprocessモジュールの基本的使い方の解説

今回はPythonのプログラムからWindowsのコマンドプロンプトを使えるsubprocessモジュールの基本的な使い方を説明します。

今回はWindowsのコマンドプロンプトを使う例の解説ですが、MacやLinuxのコマンドを使うこともできます。

公式ドキュメント

参考リンク:Python公式ドキュメント、subprocess — サブプロセス管理¶

runメソッド

PythonプログラムからWindowsのコマンドプロンプト機能を呼び出すのに、一番簡単な方法は、subprocessモジュールが提供するrunメソッドを使うことです。

subprocess.run(args*stdin=Noneinput=Nonestdout=Nonestderr=Nonecapture_output=Falseshell=Falsecwd=Nonetimeout=Nonecheck=Falseencoding=Noneerrors=Nonetext=Noneenv=Noneuniversal_newlines=None**other_popen_kwargs)

このような形で使うことになります。なにやら「(args~」以下がややこしいことになっていますが、runメソッドの引数が、

  • args
  • stdin=None
  • input=None
  • stdout=None

などというようにたくさん存在しているだけです。これらを全て設定する必要はなく、必要に応じていろいろ引数の設定を変更することになります。

ただし、第1引数argsは、コマンドプロンプトで実行するコマンドそのものを受けるため、それは基本的に必須です。

それではさっそくsubprocess.runの使い方を簡単な例で見ていきましょう。

使用例とその解説

コマンドプロンプトであるフォルダ内にある、ファイルやフォルダの一覧を取得する

今回の例は、Cドライブ>Users>hogehoge>PythonSampleフォルダ内の、ファイルとフォルダの一覧を表示させるものです。

まずはPythonではなく、コマンドプロンプトそのものを使ってそれを行ってみましょう。

コマンドプロンプトでは、フォルダ内部のファイルやフォルダの情報を取得するコマンドとして、

dir フォルダへのパス

とします。そこで今回はコマンドプロンプトに、

dir C:\Users\hogehoge\PythonSample

と入力して実行します。フォルダへのパスはみなさんの環境に合わせていろいろ変えてください。これで対象フォルダ内部のファイアルなどの一覧がコマンドプロンプト上で表示されたと思います。

Pythonでの使用例

では次にPythonのプログラムの中でコマンドプロンプトを通じてそれを実現してみましょう。まずVS Codeでもなんでもいいので、テキトーに「subprocess_test.py」というような名前のPythonファイルを新規作成します。

次に下のようなコードを書きます。

import subprocess

subprocess.run("dir C:\\Users\\hogehoge\\PythonSample", shell=True, check=True)

runメソッドは、

  • 第1引数として、”dir ~”
  • 第2引数としてshell=True
  • 第3引数として、check=True

を設定しています。

これを実行すると、同じようにPythonSampleフォルダ内部のフォルダやファイルの一覧が表示されるでしょう。

第1引数args(コマンド本体)について

まずrunメソッドの公式説明の第1引数argsについては、

  • 文字列
  • シーケンス型オブジェクト(Pythonではlist, tuple, range)

のどちらかでなければなりません。

上の使用例では文字列、

"dir C:\\Users\\hogehoge\\PythonSample"

にしてあります。

なお、コマンドを連結して、2つの処理を連続して行いたい場合は、たとえばですが、

command = "cd C:/Users/yasumitsu/Dropbox & dir"

というように、「&」記号を使って、コマンドを連結できます。

また、文字列ではなくシーケンス型オブジェクト使って、例えば今回はリストを使って書く場合は、

#コマンドプロンプトでは、「cd C:/~」のようにコマンドの後に空白を置くが、シーケンスにする場合は空白をいれない。

command_list = ["cd", "C:/Users/yasumitsu/Dropbox", "&dir"

このように書けます。

ここでは、公式解説の「Windows における引数シーケンスから文字列への変換¶」の項目で、

Windows では、 args シーケンスは以下の (MS C ランタイムで使われる規則に対応する) 規則を使って解析できる文字列に変換されます:

  1. 引数は、スペースかタブのどちらかの空白で分けられます。
  2. ダブルクオーテーションマークで囲まれた文字列は、空白が含まれていたとしても 1 つの引数として解釈されます。クオートされた文字列は引数に埋め込めます。
  3. バックスラッシュに続くダブルクオーテーションマークは、リテラルのダブルクオーテーションマークと解釈されます。
  4. バックスラッシュは、ダブルクオーテーションが続かない限り、リテラルとして解釈されます。
  5. 複数のバックスラッシュにダブルクオーテーションマークが続くなら、バックスラッシュ 2 つで 1 つのバックスラッシュ文字と解釈されます。バックスラッシュの数が奇数なら、最後のバックスラッシュは規則 3 に従って続くダブルクオーテーションマークをエスケープします。

というような処理がおこなわれ、シーケンス型から文字列へ変化されます。

フォルダパスの「¥」のエスケープ処理について

ここで少し注意しなければならないのが、コマンドプロンプト特有の問題というかWindows環境特有の問題というべきか、円記号「¥」の処理です。

Pythonでは「¥」は特殊な文字扱いになりますので、さらに「¥」をつけて「¥¥」とすることでエラーが出るのを回避しています。

上でコマンドプロンプトそのものを使う場合では、そのようなことはせず、「¥」を1つだけ使っていることと比較してください。

この点については、過去記事「Pythonの特殊記号「¥」(バックスラッシュ’\’)とエスケープシーケンスについての解説」で説明していますので読んでみてください。

第2引数shell=Trueについて

今回のコード例の第2引数shell=Trueの部分については、公式の次の説明を参考にしましょう。

Windows で shell=True とすると、COMSPEC 環境変数がデフォルトシェルを指定します。Windows で shell=True を指定する必要があるのは、実行したいコマンドがシェルに組み込みの場合だけです (例えば dir や copy)。バッチファイルやコンソールベースの実行ファイルを実行するために shell=True は必要ありません。

ここで、「COMSPEC 環境変数がデフォルトシェルを指定します」とありますが、普通はWindowsの場合はコマンドプロンプトまたはWindows Powershellになるでしょう。

特にWindows11だとデフォルトシェルがWindows Powershellです。しかし私の場合はコマンドプロンプトです。

そこで、まずshell=Trueとすることで私の環境ではコマンドプロンプトを使うように設定されるという意味です。

次に今回コマンドとして使用する「dir」コマンドは、実はコマンドプロンプト特有のコマンドで、MacのシェルやLinuxのシェルには存在しません。

そこで、「Windows で shell=True を指定する必要があるのは、実行したいコマンドがシェルに組み込みの場合だけです (例えば dir や copy」という記述がキーポイントとなります。

今回使う「dir」コマンドはまさにそれです。

第3引数check=Trueについて

第3引数のcheck=Trueについては、次の公式説明を見てください。

check に真を指定した場合、プロセスが非ゼロの終了コードで終了すると CalledProcessError 例外が送出されます。

普通Pythonプログラムから指定したコマンドを実行させてそれが成功し完了すると、「ゼロ」が返されます。しかし、エラーが出たときはゼロ以外が返されます。そこで、ゼロ以外ならばCalledProcessError 例外が返ってくるようにしている、という設定です。Falseにするとその例外が返ってきません。

例外が返ってくるほうがいろいろ都合が良いことも多いでしょう。その例外が返ってきたときに、じゃあ次どうするという処理を書けますから。