web-dev-qa-db-ja.com

サブプロセスの標準出力を変数にパイプする

サブプロセスモジュールを使用してpythongでコマンドを実行し、出力を変数に保存したい。ただし、コマンドの出力を端末に出力したくありません。このコードの場合:

def storels():
   a = subprocess.Popen("ls",Shell=True)
storels()

aに保存する代わりに、ターミナルのディレクトリ一覧を取得します。私も試しました:

 def storels():
       subprocess.Popen("ls > tmp",Shell=True)
       a = open("./tmp")
       [Rest of Code]
 storels()

これにより、lsの出力も端末に出力されます。ターミナルでls > tmpを実行しても、ターミナルにlsがまったく出力されず、tmpに保存されるため、このコマンドを多少古いos.systemメソッドで試しました。 。ただし、同じことが起こります。

編集:

Marcogのアドバイスに従った後、次のエラーが表示されますが、より複雑なコマンドを実行している場合のみです。 cdrecord --help。 Pythonはこれを吐き出します:

Traceback (most recent call last):
  File "./install.py", line 52, in <module>
    burntrack2("hi")
  File "./install.py", line 46, in burntrack2
    a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE)
  File "/usr/lib/python2.6/subprocess.py", line 633, in __init__
    errread, errwrite)
  File "/usr/lib/python2.6/subprocess.py", line 1139, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
88
Insomaniacal

lsの出力を取得するには、 stdout=subprocess.PIPE を使用します。

>>> proc = subprocess.Popen('ls', stdout=subprocess.PIPE)
>>> output = proc.stdout.read()
>>> print output
bar
baz
foo

コマンドcdrecord --helpはstderrに出力するため、その代わりにパイプする必要があります。また、以下で行ったように、コマンドをトークンのリストに分割する必要があります。または、代わりにShell=True引数を渡すこともできますが、これは完全に展開されたシェルを起動します。コマンド文字列。

>>> proc = subprocess.Popen(['cdrecord', '--help'], stderr=subprocess.PIPE)
>>> output = proc.stderr.read()
>>> print output
Usage: wodim [options] track1...trackn
Options:
    -version    print version information and exit
    dev=target  SCSI target to use as CD/DVD-Recorder
    gracetime=# set the grace time before starting to write to #.
...

Stdoutとstderrの両方に出力するコマンドがあり、それらをマージする場合は、stderrをstdoutにパイピングしてからstdoutをキャッチすることにより、それを行うことができます。

subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

Chris Morgan で述べたように、proc.communicate()の代わりにproc.read()を使用する必要があります。

>>> proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> out, err = proc.communicate()
>>> print 'stdout:', out
stdout: 
>>> print 'stderr:', err
stderr:Usage: wodim [options] track1...trackn
Options:
    -version    print version information and exit
    dev=target  SCSI target to use as CD/DVD-Recorder
    gracetime=# set the grace time before starting to write to #.
...
123
marcog

python 2.7以降を使用している場合、これを行う最も簡単な方法は subprocess.check_output() コマンドを使用することです。以下に例を示します。

output = subprocess.check_output('ls')

Stderrもリダイレクトするには、次を使用できます。

output = subprocess.check_output('ls', stderr=subprocess.STDOUT)



コマンドにパラメーターを渡す場合は、リストを使用するか、シェルを呼び出して単一の文字列を使用します。

output = subprocess.check_output(['ls', '-a'])
output = subprocess.check_output('ls -a', Shell=True)
30
amicitas

a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE)では、リストを使用するか、Shell=Trueを使用する必要があります。

これらのいずれかが機能します。前者が好ましい。

a = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE)

a = subprocess.Popen('cdrecord --help', Shell=True, stdout=subprocess.PIPE)

また、Popen.stdout.read/Popen.stderr.readを使用する代わりに、.communicate()を使用する必要があります(理由については、サブプロセスのドキュメントを参照してください)。

proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
11
Chris Morgan