Pythonで外部コマンドを実行(os.system, subprocess)
この記事では、Pythonから外部コマンドを実行する方法について説明します。`os.system`と`subprocess`モジュールを使った方法、それぞれのメリット・デメリット、セキュリティに関する考慮事項を解説します。
目次
- os.system() 関数による外部コマンドの実行
- subprocess モジュールによる外部コマンドの実行
- subprocess.run() 関数
- subprocess.Popen() クラス
- セキュリティに関する考慮事項
- 標準出力と標準エラーの処理
- 戻り値の確認
os.system() 関数による外部コマンドの実行
最も単純な方法は`os.system()`関数です。コマンドを文字列として渡し、実行します。
import os
ret = os.system('ls -l')
print(f'Return code: {ret}')
ただし、標準出力や標準エラーを直接扱うことができず、戻り値もプラットフォーム依存です。そのため、複雑な処理には向きません。
subprocess モジュールによる外部コマンドの実行
`subprocess`モジュールは、外部コマンドを実行するためのより高度な機能を提供します。`run()`、`Popen()`など、複数の関数とクラスがあります。
subprocess.run() 関数
`subprocess.run()`は、コマンドを実行し、その結果を`CompletedProcess`オブジェクトとして返します。
import subprocess
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(f'Return code: {result.returncode}')
print(f'Stdout: {result.stdout}')
print(f'Stderr: {result.stderr}')
`capture_output=True`で標準出力と標準エラーをキャプチャし、`text=True`で文字列として取得します。
subprocess.Popen() クラス
`subprocess.Popen()`は、より柔軟なコマンド実行を可能にします。非同期処理やパイプライン処理などが行えます。
import subprocess
process = subprocess.Popen(['grep', 'python'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate(input=b'This is a test line.')
print(f'Stdout: {stdout.decode()}')
print(f'Stderr: {stderr.decode()}')
stdin、stdout、stderrで標準入出力のパイプラインを制御できます。`communicate()`で入出力を行います。
セキュリティに関する考慮事項
外部コマンドを実行する際には、コマンドインジェクション攻撃に注意する必要があります。ユーザーからの入力に基づいてコマンドを構築する場合は、`shlex.quote()`関数を使用して、特別な文字を適切にエスケープ処理することが重要です。
import shlex, subprocess
user_input = 'some file.txt'
command = ['ls', shlex.quote(user_input)]
subprocess.run(command)
標準出力と標準エラーの処理
`subprocess.run()`や`subprocess.Popen()`では、`capture_output=True`オプションを使用して、コマンドの標準出力と標準エラーをPythonプログラム内で取得できます。
import subprocess
result = subprocess.run(['ls', '-l', 'nonexistent_file'], capture_output=True, text=True, check=True)
print(result.stdout)
print(result.stderr)
戻り値の確認
コマンドの実行結果を確認するには、`subprocess.run()`の`returncode`属性をチェックします。0は成功、それ以外の値はエラーを示します。
import subprocess
result = subprocess.run(['ls', '-l'], capture_output=True, text=True, check=True)
if result.returncode == 0:
print('コマンドが正常に実行されました')
else:
print('コマンドの実行に失敗しました')
関連記事
- Pythonでファイル・ディレクトリの情報を取得(os.stat, pathlib.Path)
- Pythonでファイル・ディレクトリの操作(os, shutil, pathlib)
- Pythonでコマンドライン引数を取得(sys.argv, argparse)
- Pythonでシステム情報を取得(sys, platform, os)
- Pythonでファイル・ディレクトリの存在確認(os.path.exists, os.path.isfile, os.path.isdir)
- Pythonでディレクトリを作成・削除(os.mkdir, os.makedirs, os.rmdir, shutil.rmtree)
- Pythonでファイル・ディレクトリのコピー・移動(shutil.copy, shutil.move)
- Pythonで外部コマンドを実行(os.system, subprocess)
- Pythonでファイルを開く・閉じる(open, close)
- Pythonでファイルを読み込む(read, readline, readlines)