🖥️Pythonからシェルコマンドを実行!subprocessモジュールの使い方をWindows/Mac対応で解説

⚙️ PythonコードからOSコマンドを直接動かせる

フォルダの作成、ファイル一覧の取得、プロセスの管理、アクセス権の付与——ターミナルやコマンドプロンプトで手作業していた操作が、Pythonスクリプト1本に統合できます。subprocessモジュールを使えば、WindowsのコマンドプロンプトでもMac/LinuxのターミナルでもOSのシェルコマンドをPythonから直接呼び出せるようになります。バッチ処理スクリプトとPythonコードを組み合わせたい場面で、特に威力を発揮します。

📌 subprocessモジュールとは?

subprocessは、PythonコードからOSのシェルコマンドを実行できる標準モジュールです。WindowsならコマンドプロンプトやPowerShell、Mac/Linuxならターミナル(bash/zsh)で打ち込んでいたコマンドを、Pythonスクリプト内から呼び出せます。

標準モジュールなので、pip install は不要で import subprocess だけで使えます。

🤔 どんな場面で使うのか

  • 🗂️ ディレクトリの作成・削除・一覧取得
  • 🔐 フォルダのアクセス権付与などOS管理操作
  • 🔄 他のプロセスの起動・停止
  • 🖥️ PowerShellスクリプトやbashスクリプトの呼び出し
  • 📦 Pythonで書くより、コマンドで書いた方が簡潔な処理

💡 フォルダ作成やファイル操作だけなら os モジュールや pathlib でも実現できます。subprocessの出番は「シェルコマンドで書いた方がラク」「外部ツールをPythonから呼びたい」と感じたときです。

💻 基本の使い方:subprocess.run()

subprocess.run() が最もシンプルで汎用的な関数です。第1引数にコマンド文字列を渡し、shell=True を指定するだけでコマンドが実行されます。

① ディレクトリを作成する(mkdir)

import subprocess

# Windowsの例:testというフォルダを作成
subprocess.run("mkdir test", shell=True)

このコードを実行すると、Pythonスクリプトと同じ階層に test フォルダが作成されます。たったこれだけです。

② 実行結果を取得する(stdout・returncode・stderr)

コマンドの出力をPython側で受け取りたい場合は、capture_output=Truetext=True を追加します。戻り値の CompletedProcess オブジェクトから各種情報を取り出せます。

import subprocess

# testフォルダ内のファイル一覧を取得(Windows)
cp = subprocess.run(
    r"dir .\test",
    shell=True,
    capture_output=True,
    text=True
)

print(cp.stdout)       # コマンドの標準出力(文字列)
print(cp.returncode)   # 正常終了なら 0、エラーなら 0以外
print(cp.stderr)       # エラーメッセージ(なければ空文字)

📋 CompletedProcessオブジェクトの主なプロパティ

  • 🟢 stdout:コマンドの標準出力を文字列で取得(text=True 時)
  • 🔢 returncode:正常終了 → 0、エラー → 0 以外の整数
  • 🔴 stderr:エラーメッセージを文字列で取得

存在しないディレクトリに対してコマンドを実行すると、returncode0 以外になり、stderr にエラーメッセージが格納されます。この値を使って「コマンド成功時だけ次の処理を実行する」といった分岐が書けます。

⏱️ タイムアウトの設定と例外処理

コマンドが長時間応答しないケースに備えて、timeout 引数で実行時間の上限を設定できます。指定秒数を超えると subprocess.TimeoutExpired 例外が発生するので、try/except で捕捉します。

import subprocess

try:
    cp = subprocess.run(
        "some_long_command",
        shell=True,
        capture_output=True,
        text=True,
        timeout=5   # 5秒でタイムアウト
    )
    print(cp.stdout)
except subprocess.TimeoutExpired:
    print("タイムアウトしました。処理を中断します。")

たとえばキー入力待ちで止まってしまうコマンドなど、Pythonプログラムが無限待機に陥る危険を防げます。

🪟 PowerShellコマンドを実行する(Windows)

WindowsでPowerShellのコマンドをsubprocessから呼び出すには、powershell -command "..." の形式で第1引数に指定します。パスにバックスラッシュが含まれる場合は raw文字列プレフィックス r を付けておくと安全です。

import subprocess

cp = subprocess.run(
    r'powershell -command "Get-ChildItem C:\Users"',
    shell=True,
    capture_output=True,
    text=True
)
print(cp.stdout)

PowerShellコマンドを二重引用符で囲み、run()の引数全体はシングル引用符で囲むのがポイントです。

🍎 Mac/Linuxでの使い方

Mac/Linuxでも書き方はほぼ同じです。コマンドをbash/zsh用に変えるだけで動作します。

import subprocess

# Mac/Linux:カレントディレクトリのファイル一覧
cp = subprocess.run(
    "ls -la ./test",
    shell=True,
    capture_output=True,
    text=True
)
print(cp.stdout)

✅ subprocess.run() よく使う引数チートシート

  • 🔹 shell=True:シェル経由でコマンドを実行(文字列形式で渡す場合に必須)
  • 🔹 capture_output=True:stdout・stderrをPythonで受け取れるようにする
  • 🔹 text=True:stdout・stderrをバイト列ではなく文字列で受け取る
  • 🔹 timeout=秒数:指定秒数を超えたら TimeoutExpired 例外を発生させる
  • 🔹 cp.stdout:コマンドの標準出力(文字列)
  • 🔹 cp.returncode:終了コード(0=正常、0以外=エラー)
  • 🔹 cp.stderr:エラーメッセージ(文字列)

🖥️ 快適な開発環境づくりにおすすめのアイテム

バッチ処理スクリプトやOS操作の自動化は、複数のターミナルウィンドウを並べて作業することが多くなります。広い画面とキーボード環境を整えるだけで、開発効率が大きく変わります🚀

❓ よくある質問 FAQ

🤔 Q1. shell=True と shell=False の違いは何ですか?

shell=True にすると、コマンドをシェル(cmd.exeやbash)経由で実行します。パイプ(|)やワイルドカード(*)などシェル機能が使えます。shell=False(デフォルト)では、コマンドをリスト形式(["ls", "-la"])で渡して直接実行します。信頼できないユーザー入力をコマンドに含める場合は、セキュリティ上 shell=False の方が安全です。

🤔 Q2. capture_output=True を付けないと標準出力はどうなりますか?

capture_output を指定しない場合、コマンドの出力はそのままターミナル画面に表示されますが、Python変数として受け取ることはできません。cp.stdoutNone になります。Python側で出力を処理・加工したい場合は必ず capture_output=Truetext=True を指定してください。

🤔 Q3. returncode が 0 以外の値を確認する方法はありますか?

subprocess.run()check=True を追加すると、returncode が 0 以外のとき自動で subprocess.CalledProcessError 例外を発生させられます。try/except subprocess.CalledProcessError でまとめてエラー処理を書けるので、returncode を自分でチェックする手間が省けます。

🤔 Q4. Popen と run() はどう違いますか?

subprocess.run() はコマンドの完了を待ってから制御を返す「同期実行」です。一方 subprocess.Popen() はコマンドを非同期で起動し、Pythonコードと並行して処理できる「非同期実行」に対応しています。複数のコマンドを同時に走らせたい場合や、コマンドの実行中にPython側で別の処理を続けたい場合は Popen を使います。

🤔 Q5. Windowsのコマンドプロンプトとbashで同じコードを使えますか?

使えません。コマンド文字列はOS固有のものになります。クロスプラットフォームで動かしたい場合は、sys.platformplatform.system() でOSを判定し、分岐してコマンドを切り替える方法が一般的です。または、ファイル操作の範囲なら pathlibshutil モジュールを使ってOS差異を吸収する方が堅牢です。

🎯 まとめ

subprocessモジュールの基本は「subprocess.run(コマンド文字列, shell=True)」の一行から始まります。capture_output=Truetext=True を加えれば出力を文字列として受け取れ、returncode でコマンドの成否を確認、timeout でハングアップを防げます。PythonコードとシェルコマンドをうまくミックスさせることでOS操作の自動化がさらに強力になります。シェルコマンドで書いた方が楽な処理に出くわしたときは、ぜひsubprocessを活用してみてください⚙️✨

あざらし

はじめまして、あざらしです。 フリーターからエンジニア会社へ就職し、 現在はフリーランスのシステムエンジニアとして働いています。 本業のエンジニア業のかたわら、 ✍️ ブログ運営 と「収入の柱を増やす挑戦」を少しずつ続けています。 フリーター時代から比べると、 段階的に収入が増えていくのを実感できるのが素直にうれしい今日この頃。 このブログでは、日々の気づき・体験談 IT・ガジェット・ゲーム系の話 「調べて分かったこと」を噛み砕いた解説 などを中心に、ジャンルに縛られない雑記ブログとして発信しています。 「自分と同じように悩んでいる人のヒントになればいいな」 そんな気持ちで更新中です。 👉 プロフィール詳細は、名前「あざらし」をクリックしてください