【Python】subprocess|使い方・サンプルコードで外部コマンドを自由自在に操る!

Pythonで外部コマンドを自由自在に操りたいですか?この記事では、subprocessモジュールの使い方を初心者にもわかりやすく解説します。

サンプルコードを豊富に掲載しているので、実際に手を動かしながら理解を深められます。

この記事を読めば、Pythonから外部コマンドを実行し、様々な処理を自動化できるようになります。

ぜひ最後まで読んで、あなたのPythonスキルをレベルアップさせましょう!

この記事でわかることは以下のとおりです。

スポンサーリンク

Python subprocessとは

subprocessモジュールは、Pythonから新たなプロセスを立ち上げ、外部コマンドを実行するための標準ライブラリです。

これを使うことで、PythonスクリプトからOSのコマンドや他の実行ファイルを呼び出し、その結果を受け取るといった操作が可能になります。

外部コマンド実行の標準ライブラリ

Pythonで外部コマンドを実行する方法はいくつかありますが、現在ではsubprocessモジュールが推奨されています。

以前はos.systemやcommandsといったモジュールも使われていましたが、機能や柔軟性の面でsubprocessモジュールが優れているからです。

subprocessモジュールは、外部プロセスとの連携に必要な機能が豊富に揃っています。

commandsモジュールとの違い

以前使われていたcommandsモジュールは、現在ではメンテナンスが終了しており、将来的に廃止される予定です。

そのため、新しくコードを書く場合は、迷わずsubprocessモジュールを使用しましょう。

subprocessモジュールは、commandsモジュールに比べて機能が豊富で、より柔軟な制御が可能です。

subprocessでできること

subprocessモジュールを使うと、Pythonから様々なことができます。

具体的には、以下のようなことが可能です。

例えば、画像処理ソフトを呼び出して画像を加工したり、ネットワークコマンドを実行してサーバーの状態を確認したりできます。

subprocessモジュールをマスターすることで、Pythonでの開発がより効率的になるでしょう。

スポンサーリンク

subprocessの基本

Pythonで外部コマンドを実行したいなら、subprocessモジュールがおすすめです!subprocessモジュールを使えば、PythonプログラムからOSのコマンドや他のプログラムを実行できます。

subprocessモジュールを使いこなして、Pythonスキルをレベルアップさせましょう!

Pythonで外部コマンドを実行するために、subprocessモジュールは重要な役割を果たします。

subprocessモジュールを使うことで、Pythonスクリプトから直接システムコマンドを実行したり、他のプログラムを起動したりできます。

外部コマンドの実行、入出力パイプの接続、終了コードの取得などが可能です。

subprocess.run()

subprocess.run()は、subprocessモジュールで最も推奨されるコマンド実行方法です。

引数として与えられたコマンドを実行し、その完了を待ちます。

実行結果はCompletedProcessインスタンスとして返されます。

CompletedProcessインスタンスには、実行したコマンド、終了コード、標準出力、標準エラー出力などが含まれています。

例えば、subprocess.run([‘ls’, ‘-l’])と記述することで、Linux環境でファイルのリストを表示するls -lコマンドを実行できます。

Windows環境であれば、subprocess.run([‘dir’])で同様の操作が可能です。

capture_output=Trueを指定すると、コマンドの実行結果を文字列として取得できます。

エラーが発生した場合は、check=Trueを指定することでCalledProcessError例外が発生し、エラー処理も可能です。

Popenオブジェクト

subprocess.Popen()は、より高度な使い方をしたい場合に役立つ下層インターフェースです。

subprocess.run()とは異なり、Popenオブジェクトは新しいプロセスを起動するとすぐに制御を返します。

そのため、非同期処理や並列処理を実装する際に便利です。

Popenオブジェクトを使用すると、プロセスの標準入力、標準出力、標準エラー出力をパイプで接続したり、環境変数を設定したりするなど、より詳細な制御が可能です。

例えば、複数のコマンドをパイプで連結して実行したり、バックグラウンドで長時間実行されるプロセスを管理したりする際に役立ちます。

標準出力と標準エラー出力

subprocessモジュールでは、コマンドの実行結果として標準出力と標準エラー出力を取得できます。

標準出力は、コマンドが正常に実行された場合の出力であり、標準エラー出力は、エラーが発生した場合の出力です。

subprocess.run()でcapture_output=Trueを指定すると、これらの出力を取得できます。

標準出力と標準エラー出力を適切に処理することで、コマンドの実行結果を詳細に分析したり、エラーが発生した場合に適切な対処を行ったりできます。

例えば、ログファイルに書き込んだり、特定の条件に基づいて処理を分岐させたりすることが可能です。

終了コード

subprocessモジュールで実行したコマンドの終了コードは、コマンドが正常に完了したかどうかを示す重要な情報です。

終了コードが0の場合は、コマンドが正常に完了したことを意味し、0以外の値の場合は、エラーが発生したことを意味します。

subprocess.run()で返されるCompletedProcessインスタンスのreturncode属性を確認することで、終了コードを取得できます。

check=Trueを指定した場合は、終了コードが0以外の場合にCalledProcessError例外が発生し、エラー処理を強制できます。

終了コードを適切に処理することで、コマンドの実行結果を正確に判断し、エラーが発生した場合に適切な対処を行えます。

タイムアウト設定

subprocessモジュールでは、コマンドの実行にタイムアウトを設定できます。

subprocess.run()のtimeout引数に秒数を指定することで、コマンドが指定された時間内に完了しない場合にTimeoutExpired例外が発生します。

タイムアウトを設定することで、無限ループやハングアップなどの問題が発生した場合に、プログラムが停止してしまうのを防ぐことができます。

特に、外部コマンドの実行時間が予測できない場合や、ネットワーク経由でコマンドを実行する場合に有効です。

スポンサーリンク

サンプルコード

ls -l コマンド(ファイル一覧表示)

ファイルの一覧を表示するには、ls -lコマンドを使用します。

subprocess.run()関数を使うことで、Pythonからこのコマンドを実行できます。

実行結果の例を以下に示します。

ls -lコマンドを実行すると、ファイルの詳細な情報が得られるため、ファイル管理やスクリプト作成に役立ちます。

たまに実行時のディレクトリによって結果が変わることもあるので、注意が必要です。

echo Hello, World!(文字列出力)

文字列を出力するには、echoコマンドを使用します。

「Hello, World!」と出力する例を見ていきましょう。

以下に具体的なコードと実行結果を示します。

echoコマンドは、指定した文字列を標準出力に出力するシンプルなコマンドです。

プログラミングの学習を始めたばかりの頃によく使うコマンドをPythonから実行できるのは面白いですよね。

ファイルから特定の文字列を検索するには、grepコマンドを使用します。

grepは、ファイル内からパターンに一致する行を抽出する強力なツールです。

grepコマンドをsubprocessから使うことで、Pythonスクリプト内で特定のパターンを持つ行を効率的に検索できます。

grepの結果をさらに処理することで、ログ分析やデータ抽出などの応用も可能です。

複数コマンド実行(パイプ処理)

複数のコマンドを組み合わせて実行するには、パイプ処理を利用します。

パイプ処理を使うと、あるコマンドの出力を別のコマンドの入力として使用できます。

例えば、ls -lコマンドの結果をgrepコマンドでフィルタリングすることで、特定のファイルだけを抽出できます。

shell=Trueとすることで、シェルを介してコマンドを実行し、パイプ処理を可能にします。

ファイルリダイレクト

コマンドの出力結果をファイルに書き出すには、リダイレクトを使用します。

リダイレクトを使うことで、コマンドの実行結果をファイルに保存したり、ファイルの内容をコマンドの入力として使用したりできます。

以下は、echoコマンドの出力をファイルにリダイレクトする例です。

この例では、echoコマンドの出力がoutput.txtというファイルにリダイレクトされます。

リダイレクトを使うことで、コマンドの出力をファイルに保存し、後で利用できます。

ファイル操作は、自動化スクリプトで非常に役立ちます。

スポンサーリンク

エラー処理とセキュリティ

Pythonで外部コマンドを実行するsubprocessモジュールは便利ですが、エラー処理とセキュリティ対策を怠ると、予期せぬ問題やセキュリティリスクに繋がる可能性があります。

ここでは、subprocessモジュール利用時のエラー処理とセキュリティ対策について解説します。

例外処理

subprocess.run()関数でcheck=Trueを指定すると、コマンドが正常に実行されなかった場合にsubprocess.CalledProcessError例外が発生します。

この例外をtry…except構文でキャッチすることで、エラー発生時の処理を記述できます。

import subprocess

try:
    subprocess.run(['存在しないコマンド'], check=True, capture_output=True, text=True)
except subprocess.CalledProcessError as e:
    print(f"エラーが発生しました: {e}")
    print(f"終了コード: {e.returncode}")
    print(f"標準エラー出力: {e.stderr}")

例外処理を適切に行うことで、プログラムの安定性を高められます。

コマンドインジェクション対策

subprocessモジュールでshell=Trueを使用すると、コマンドインジェクションというセキュリティ上の脆弱性が生まれるかもしれません。

コマンドインジェクションとは、ユーザーからの入力値をそのままコマンドに組み込むことで、攻撃者が意図しないコマンドを実行できてしまうかもしれない攻撃手法です。

例えば、以下のようなコードがあったとします。

import subprocess

filename = input("ファイル名を入力してください: ")

try:
    subprocess.run(f'ls -l {filename}', shell=True, check=True)
except subprocess.CalledProcessError as e:
    print(f"エラーが発生しました: {e}")
    print(f"終了コード: {e.returncode}")

この場合、ユーザーが「; rm -rf /」のような悪意のあるファイル名を入力すると、lsコマンドの後にrmコマンドが実行され、システムに深刻な被害を与える可能性があります。

shlex.quote()

コマンドインジェクションを防ぐためには、shlex.quote()関数を使用して、ユーザーからの入力値をエスケープ処理する必要があります。

shlex.quote()関数は、文字列を安全にクォートし、シェルによる解釈を防ぎます。

import subprocess
import shlex

filename = input("ファイル名を入力してください: ")

# ファイル名を安全にする
safe_filename = shlex.quote(filename)

# shell=Trueを使用してコマンドを文字列として渡す
subprocess.run(f'ls -l {safe_filename}', shell=True)

shlex.quote()を使用することで、悪意のある入力値がコマンドとして実行されるのを防ぎ、セキュリティリスクを軽減できます。

危険な引数

subprocess.run()関数の引数に直接ユーザーからの入力値を含めることも、コマンドインジェクションのリスクを高める行為です。

例えば、以下のようなコードは危険です。

import subprocess
import shlex

command = input("実行するコマンドを入力してください: ")

# コマンドをリスト形式に分割
args = shlex.split(command)

# コマンドを実行
subprocess.run(args)

この場合、ユーザーが入力したコマンドがそのまま実行されるため、攻撃者は任意のコマンドを実行できてしまいます。

安全なコードにするには、コマンドと引数をリスト形式で指定し、shell=Falseで使用してください。

import subprocess
import shlex

command = input("実行するコマンドを入力してください: ")

# コマンドをリスト形式に分割
args = shlex.split(command)

# コマンドを実行
subprocess.run(args, shell=False)

subprocessモジュールを使う際は、以下の点に注意して、セキュリティ対策を徹底することが大切です。

セキュリティ対策をしっかりと行うことで、安全にsubprocessモジュールを活用できます。

スポンサーリンク

応用例とユースケース

subprocessモジュールは、Pythonから外部コマンドを実行するための機能を提供し、自動化スクリプト、システム管理、ログ解析など、さまざまな分野で活用されています。

モジュールを使うことで、Pythonだけでは実現できない処理も可能になり、開発の幅を広げられます。

自動化スクリプト

自動化スクリプトでsubprocessモジュールを活用すると、例えば、ファイル操作やバックアップ処理などを自動化できます。

定期的なタスクを自動化することで、人的ミスを減らし、効率的なシステム運用を実現します。

システム管理

システム管理においてsubprocessモジュールは、サーバーの監視や設定変更といったタスクを自動化するために利用されています。

例えば、CPU使用率やメモリ使用量などを監視し、異常があれば自動的に再起動するスクリプトを作成できます。

システム管理者は、これらのスクリプトを活用することで、サーバーの安定稼働を維持し、迅速な問題解決を図ることが可能です。

ログ解析

ログ解析でsubprocessモジュールを活用すると、大量のログデータから必要な情報を効率的に抽出できます。

特定のキーワードを含むログ行を抽出したり、エラーメッセージの発生頻度を分析したりすることが可能です。

このようなログ解析は、システムの問題特定やパフォーマンス改善に役立ちます。

スポンサーリンク

おすすめsubprocessモジュール

Pythonで外部コマンドを実行する際に、subprocessモジュールは欠かせない存在です。

subprocessモジュールは、新しいプロセスを起動し、その入出力を制御することで、Pythonスクリプトから外部のプログラムやコマンドを実行できます。

外部コマンド実行の可能性

subprocessモジュールを利用すると、Pythonの標準機能だけでは実現できない処理も可能になります。

例えば、画像処理ソフトを呼び出して画像を加工したり、ネットワークコマンドを実行してサーバーの状態を確認したりできます。

OSに標準搭載されているコマンドであれば、環境構築の手間も少なく、すぐに利用できるでしょう。

subprocessモジュールは、Pythonと外部プログラムを連携させるための強力なツールです。

Pythonスキルのレベルアップ

subprocessモジュールを使いこなせるようになると、Pythonでできることが格段に広がります。

他のプログラミング言語で書かれたツールや、OSのコマンドラインツールをPythonから利用できるようになるからです。

subprocessモジュールは、単なるモジュールではなく、Pythonプログラミングの可能性を広げるための鍵となるでしょう。

自動化による効率化

subprocessモジュールは、定型的な作業を自動化するのに非常に役立ちます。

例えば、毎日同じ時間にWebサイトからデータをダウンロードして、加工するといったタスクをPythonスクリプトで記述し、自動的に実行できます。

手作業で行っていた作業を自動化することで、時間と労力を大幅に削減し、より創造的な仕事に集中できるでしょう。

subprocessモジュールは、日々の業務を効率化するための強力な味方になります。

スポンサーリンク

よくある質問(FAQ)

Q
subprocess.run()とsubprocess.Popen()、どちらを使うべきですか?
A

subprocess.run()は、コマンド実行が完了するまで待機し、結果をまとめて取得したい場合に推奨されます。一方、subprocess.Popen()は、非同期処理やより細かい制御が必要な場合に利用すると良いでしょう。

Q
コマンド実行時にエラーが発生した場合、どのように対処すれば良いですか?
A

subprocess.run()を使う場合は、check=Trueを指定すると、エラー時に例外subprocess.CalledProcessErrorが発生します。この例外をtry-except構文で処理することで、エラー発生時の対応を記述できます。

Q
コマンドインジェクションとは何ですか?どのように対策すれば良いですか?
A

コマンドインジェクションとは、ユーザーからの入力値をそのままコマンドに組み込むことで、攻撃者が意図しないコマンドを実行できてしまうセキュリティ上の脆弱性です。対策としては、shell=Trueの使用を避け、shlex.quote()関数で入力値をエスケープ処理することが重要です。

Q
タイムアウト設定はどのように行うのですか?
A

subprocess.run()関数のtimeout引数に秒数を指定することで、コマンド実行のタイムアウトを設定できます。指定時間を超えるとTimeoutExpired例外が発生し、プログラムの停止を防げます。

Q
標準出力と標準エラー出力を取得するにはどうすれば良いですか?
A

subprocess.run()でcapture_output=Trueを指定すると、標準出力と標準エラー出力をバイト形式で取得できます。text=Trueを合わせて指定すると、テキスト形式で取得できます。

Q
subprocessモジュールを使う上で、セキュリティ面で気をつけることはありますか?
A

shell=Trueの使用は、シェルインジェクションのリスクを高めます。どうしても必要な場合にのみ使用し、ユーザーからの入力値をエスケープ処理することが重要です。コマンドと引数をリスト形式で指定し、shell=Falseで使用することを推奨します。

参考

まとめ

この記事では、Pythonのsubprocessモジュールについて、基本的な使い方から応用例、セキュリティ対策まで詳しく解説しました。

この記事を参考に、subprocessモジュールを使いこなして、Pythonでの外部コマンド実行を自由自在に操ってみましょう。

コメント