web-dev-qa-db-ja.com

subprocess.call()の出力を取得する

subprocess.call()を使用して実行したプロセスの出力を取得する方法を教えてください。

stdoutStringIO.StringIOオブジェクトを渡すと、このエラーが発生します。

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 444, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 588, in __init__
    errread, errwrite) = self._get_handles(stdin, stdout, stderr)
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 945, in _get_handles
    c2pwrite = stdout.fileno()
AttributeError: StringIO instance has no attribute 'fileno'
>>> 
232

subprocess.call()からの出力はファイルにのみリダイレクトされるべきです。

代わりにsubprocess.Popen()を使うべきです。次に、stderr、stdout、stdinのいずれかまたは両方のパラメータにsubprocess.PIPEを渡し、communicate()メソッドを使用してパイプから読み取ることができます。

from subprocess import Popen, PIPE

p = Popen(['program', 'arg1'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, err = p.communicate(b"input data that is passed to subprocess' stdin")
rc = p.returncode

その理由は、subprocess.call()によって使用されるファイルのようなオブジェクトは実際のファイルディスクリプタを持たなければならず、したがってfileno()メソッドを実装する必要があるからです。ファイルのようなオブジェクトを使用するだけではうまくいきません。

詳しくは こちら をご覧ください。

183
Mike

Pythonのバージョンが2.7以上の場合、 subprocess.check_output を使用することができます。これは基本的に必要な処理を正確に実行します(標準出力を文字列として返します)。

簡単な例(Linux版、注を参照):

import subprocess

print subprocess.check_output(["ping", "-c", "1", "8.8.8.8"])

PingコマンドはLinux表記(countの場合は-c)を使用していることに注意してください。 Windowsでこれを試した場合、同じ結果になるように-nに変更することを忘れないでください。

以下にコメントされているように、あなたは この他の答え でより詳細な説明を見つけることができます。

236
sargue

次のような解決策があります。実行された外部コマンドの終了コード、標準出力、および標準エラー出力もキャプチャします。

import shlex
from subprocess import Popen, PIPE

def get_exitcode_stdout_stderr(cmd):
    """
    Execute the external command and get its exitcode, stdout and stderr.
    """
    args = shlex.split(cmd)

    proc = Popen(args, stdout=PIPE, stderr=PIPE)
    out, err = proc.communicate()
    exitcode = proc.returncode
    #
    return exitcode, out, err

cmd = "..."  # arbitrary external command, e.g. "python mytest.py"
exitcode, out, err = get_exitcode_stdout_stderr(cmd)

私はそれについてのブログ記事も持っています ここ

編集:解決策は新しいものに更新されましたが、それは一時ファイルに書き込む必要はありません。ファイル.

47
Jabba

Python 3.5以降では、サブプロセスモジュールから run関数を使うことをお勧めします 。これはCompletedProcessオブジェクトを返し、そこから戻りコードだけでなく出力も簡単に取得できます。

from subprocess import PIPE, run

command = ['echo', 'hello']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
print(result.returncode, result.stdout, result.stderr)
40

私は最近これを行う方法を考え出したところです、そして、これが私の現在のプロジェクトからのいくつかのサンプルコードです:

#Getting the random picture.
#First find all pictures:
import shlex, subprocess
cmd = 'find ../Pictures/ -regex ".*\(JPG\|NEF\|jpg\)" '
#cmd = raw_input("Shell:")
args = shlex.split(cmd)
output,error = subprocess.Popen(args,stdout = subprocess.PIPE, stderr= subprocess.PIPE).communicate()
#Another way to get output
#output = subprocess.Popen(args,stdout = subprocess.PIPE).stdout
ber = raw_input("search complete, display results?")
print output
#... and on to the selection process ...

これで、コマンドの出力が変数 "output"に格納されました。 "stdout = subprocess.PIPE"は、Popen内から 'stdout'という名前のファイルオブジェクトを作成するようにクラスに指示します。私が言うことができるものから、communication()メソッドは単にあなたが実行したプロセスからの出力とエラーのタプルを返すための便利な方法として機能します。また、このプロセスはPopenをインスタンス化するときにも実行されます。

28
Cheesemold

Ipythonシェルの場合:

In [8]: import subprocess
In [9]: s=subprocess.check_output(["echo", "Hello World!"])
In [10]: s
Out[10]: 'Hello World!\n'

サルグの答えに基づく。頼りにしている功績。

12
jhegedus

以下は、プロセスの標準出力と標準エラー出力を単一の変数にまとめたものです。 Python 2と3に対応しています。

from subprocess import check_output, CalledProcessError, STDOUT

command = ["ls", "-l"]
try:
    output = check_output(command, stderr=STDOUT).decode()
    success = True 
except CalledProcessError as e:
    output = e.output.decode()
    success = False

コマンドが配列ではなく文字列の場合は、これに次のように付けます。

import shlex
command = shlex.split(command)
6
Zags