[解決済み] シェルコマンドの実行と出力のキャプチャ
質問
シェルコマンドを実行し、その出力を返す関数を書きたい 文字列として エラーメッセージでも成功メッセージでもかまいません。私はただ、コマンドラインで得られたであろうのと同じ結果を得たいだけです。
そのようなことをするコード例はどのようなものでしょうか?
例えば
def run_command(cmd):
# ??????
print run_command('mysqladmin create test -uroot -pmysqladmin12')
# Should output something like:
# mysqladmin: CREATE DATABASE failed; error: 'Can't create database 'test'; database exists'
解決方法は?
公式にメンテナンスされているすべてのバージョンの Python において、最もシンプルなアプローチは
subprocess.check_output
関数を使用します。
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_output
は、入力として引数のみを受け取る単一のプログラムを実行します。
1
にプリントされた通りの結果を返します。
stdout
. に入力を書き込む必要がある場合
stdin
にスキップして
run
または
Popen
セクションを作成します。複雑なシェルコマンドを実行したい場合は、以下の説明を参照してください。
shell=True
は、この回答の最後にあります。
は
check_output
関数は、公式にメンテナンスされているすべてのバージョンのPythonで動作します。しかし、より最近のバージョンでは、より柔軟なアプローチが可能です。
Pythonの最新バージョン(3.5以上)です。
run
を使用している場合
Python 3.5+
で、かつ
後方互換性が必要ない
は、新しい
run
関数は、ほとんどのタスクで公式ドキュメントに推奨されています。これは、非常に一般的で高レベルな API を
subprocess
モジュールを使用します。プログラムの出力をキャプチャするには
subprocess.PIPE
フラグを
stdout
キーワード引数を指定します。次に
stdout
属性が返されます。
CompletedProcess
オブジェクトを作成します。
>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
戻り値は
bytes
オブジェクトを作成します。もし適切な文字列が欲しい場合は
decode
それを 呼び出されたプロセスがUTF-8でエンコードされた文字列を返すと仮定します。
>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
必要であれば、これをすべて1行に圧縮することができる。
>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
入力を渡したい場合は、プロセスの
stdin
を渡すことができます。
bytes
オブジェクトを
input
キーワード引数を指定します。
>>> cmd = ['awk', 'length($0) > 5']
>>> ip = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=ip)
>>> result.stdout.decode('utf-8')
'foofoo\n'
を渡すことで、エラーを捕捉することができます。
stderr=subprocess.PIPE
(キャプチャは
result.stderr
) または
stderr=subprocess.STDOUT
(にキャプチャー)。
result.stdout
を通常の出力と一緒に出力します)。もし
run
がゼロ以外の終了コードを返したときに例外を投げるようにするには、 プロセスに
check=True
. (または
returncode
属性の
result
上記) セキュリティが心配でない場合、より複雑なシェルコマンドを実行するために
shell=True
この回答の最後で説明されているように
Pythonの後のバージョンでは、上記がさらに効率化されます。Python 3.7+では、上記のワンライナーは次のように綴ることができます。
>>> subprocess.run(['ls', '-l'], capture_output=True, text=True).stdout
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
使用方法
run
この方法では、以前の方法に比べてほんの少し複雑さが増します。しかし、これで、必要なことはほとんど何でも
run
関数だけです。
古いバージョンのPython (3-3.4):詳細はこちら
check_output
古いバージョンの Python を使っている場合、あるいは適度な後方互換性が必要な場合は
check_output
関数は、上記で簡単に説明したように これは Python 2.7 以降で利用可能です。
subprocess.check_output(*popenargs, **kwargs)
と同じ引数を取ります。
Popen
(下記参照) そして、プログラムの出力を含む文字列を返します。この回答の冒頭に、より詳細な使用例があります。Python 3.5+の場合。
check_output
を実行することと同じです。
run
と
check=True
と
stdout=PIPE
を返します。
stdout
属性で指定します。
を渡すことができます。
stderr=subprocess.STDOUT
を使用すると、返される出力にエラーメッセージが含まれるようになります。セキュリティが心配でないときは、より複雑なシェルコマンドを実行することもできます。
shell=True
この回答の最後に説明されているように
からのパイプが必要な場合
stderr
またはプロセスへの入力を渡します。
check_output
は、このタスクに対応できません。このような場合は
Popen
の例は、そのような場合です。
複雑なアプリケーションとレガシーバージョンのPython(2.6以下)。
Popen
深い後方互換性が必要な場合、あるいは
check_output
または
run
を提供する場合は、直接
Popen
これはサブプロセス用の低レベル API をカプセル化したものです。
は
Popen
コンストラクタは
単一のコマンド
引数なし、または
リスト
コマンドを最初の項目として含み、その後に任意の数の引数が続き、それぞれがリストの個別の項目となる。
shlex.split
は、文字列を適切にフォーマットされたリストにパースするのに役立ちます。
Popen
オブジェクトは
ホストのさまざまな引数
プロセスのIO管理および低レベルの設定に使用されます。
入力を送信し、出力をキャプチャすること。
communicate
は、ほとんどの場合、好ましい方法です。というように。
output = subprocess.Popen(["mycmd", "myarg"],
stdout=subprocess.PIPE).communicate()[0]
または
>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
を設定した場合
stdin=PIPE
,
communicate
を経由してプロセスにデータを渡すこともできます。
stdin
:
>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo
備考
Aaron Hallの回答
を設定する必要があることを示唆しています。
stdout
,
stderr
および
stdin
をすべて
PIPE
(または
DEVNULL
を取得するために
communicate
が全く動作しない。
まれに、複雑なリアルタイム出力キャプチャが必要な場合があります。
バルテック
の回答は、今後の方向性を示唆していますが、「Select」以外の方法は、「Select」です。
communicate
は、慎重に使用しないとデッドロックになりやすい。
上記の関数と同様に、セキュリティが気にならない場合は
shell=True
.
備考
1. シェルコマンドの実行
shell=True
引数
通常、各呼び出しは
run
,
check_output
または
Popen
コンストラクタは
単一プログラム
. つまり、派手なバッシュスタイルのパイプはありません。もし、複雑なシェルコマンドを実行したい場合は
shell=True
この3つの関数はすべてサポートしています。例えば
>>> subprocess.check_output('cat books/* | wc', shell=True, text=True)
' 1299377 17005208 101299376\n'
しかし、このようにすると セキュリティ上の懸念 . 軽いスクリプト以上のことをするのであれば、各プロセスを別々に呼び出し、それぞれの出力を入力として次のプロセスに渡す方が良いでしょう。
run(cmd, [stdout=etc...], input=other_output)
または
Popen(cmd, [stdout=etc...]).communicate(other_output)
パイプを直接つなげる誘惑は強いですが、それに打ち勝ってください。そうしないと、デッドロックが発生したり、次のような面倒なことをしなければならなくなる可能性があります。 これ .
関連
-
[解決済み】インポートエラー。モジュール名 urllib2 がない
-
[解決済み】cアンダースコア式`c_`は、具体的に何をするのですか?
-
[解決済み] Pythonのリストメソッドであるappendとextendの違いは何ですか?
-
[解決済み] 最小限の驚き」と「変更可能なデフォルトの引数
-
[解決済み] シェルで、「2>&1」はどういう意味ですか?
-
[解決済み] ディレクトリが存在しない場合のみmkdirする方法は?
-
[解決済み] Bashでコマンドの出力に変数を設定するにはどうすればよいですか?
-
[解決済み] Git上でシェルコマンドを実行する際に使用するSSH-keyの秘密鍵を指定する方法は?
-
[解決済み] 整数の合計を1行に1つずつ表示するシェルコマンド?
-
[解決済み】__str__と__repr__の違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] [Solved] sklearn error ValueError: 入力に NaN、infinity または dtype('float64') に対して大きすぎる値が含まれている。
-
[解決済み] _tkinter.TclError: 表示名がなく、$DISPLAY環境変数もない。
-
[解決済み】ilocが「IndexError: single positional indexer is out-of-bounds」を出す。
-
[解決済み] データ型が理解できない
-
[解決済み】TypeError: re.findall()でバイトのようなオブジェクトに文字列パターンを使用することはできません。)
-
[解決済み】インポートエラー。モジュール名 urllib2 がない
-
[解決済み】Python Error: "ValueError: need more than 1 value to unpack" (バリューエラー:解凍に1つ以上の値が必要です
-
[解決済み】NameError: 名前 'self' が定義されていません。
-
[解決済み] os.systemの出力を変数に代入し、画面に表示されないようにする [重複] 。
-
[解決済み] subprocess.Popen 呼び出しの出力を文字列で保存する [重複] 。