web-dev-qa-db-ja.com

Pythonでsubprocess.check_output()をどのように使用しますか?

Subprocess.check_output()に関するドキュメントを見つけましたが、引数のあるドキュメントを見つけることができず、ドキュメントの深さがあまりありません。 Python 3を使用しています(ただし、Python 3を介してPython 2ファイルを実行しようとしています)

このコマンドを実行しようとしています:python py2.py -i test.txt

-iはargparseの位置引数、test.txtは-i、py2.pyは実行するファイルです

私は以下を含む多くの(動作しない)バリエーションを試しました:py2output = subprocess.check_output([str('python py2.py '),'-i', 'test.txt'])

py2output = subprocess.check_output([str('python'),'py2.py','-i', test.txt'])

55
JOHANNES_NYÅTT

正解(Python 2.7以降を使用、check_output()当時導入されていた ):

py2output = subprocess.check_output(['python','py2.py','-i', 'test.txt'])

実証するために、ここに私の2つのプログラムを示します。

py2.py:

import sys
print sys.argv

py3.py:

import subprocess
py2output = subprocess.check_output(['python', 'py2.py', '-i', 'test.txt'])
print('py2 said:', py2output)

実行する:

$ python3 py3.py
py2 said: b"['py2.py', '-i', 'test.txt']\n"

各バージョンの問題点は次のとおりです。

py2output = subprocess.check_output([str('python py2.py '),'-i', 'test.txt'])

まず、str('python py2.py')'python py2.py'とまったく同じです。strを取得し、strを呼び出してstrに変換します。これにより、コードは読みにくくなり、長くなり、さらに遅くなりますが、利点はありません。

さらに深刻なのは、python py2.pyという名前のプログラムを実際に実行しようとしていない限り、/usr/bin/python\ py2.pyを単一の引数にすることはできません。あなたはそうではありません。たとえば、/usr/bin/pythonを最初の引数py2.pyで実行しようとしています。そのため、リスト内の要素を個別に作成する必要があります。

2番目のバージョンで修正されますが、'の前にtest.txt'がありません。これにより、おそらくEOL while scanning string literalと言うSyntaxErrorが表示されます。

その間、どのようにしてドキュメントを見つけたのかはわかりませんが、引数のある例は見つかりませんでした。最初の例は次のとおりです。

>>> subprocess.check_output(["echo", "Hello World!"])
b'Hello World!\n'

追加の引数"echo"を指定して"Hello World!"コマンドを呼び出します。

また:

-iはargparseの位置引数であり、test.txtは-iです

-inotではなく、オプションの引数であると確信しています。そうでなければ、文の後半は意味をなしません。

62
abarnert

@abarnertが言及したものに追加する

より良い方法は、例外をキャッチすることです

import subprocess
try:
    py2output = subprocess.check_output(['python', 'py2.py', '-i', 'test.txt'],stderr= subprocess.STDOUT)  
    #print('py2 said:', py2output)
    print "here"
except subprocess.CalledProcessError as e:
    print "Calledprocerr"

このstderr = subprocess.STDOUTは、stderrでfilenotfoundエラーを取得しないようにするためのものです。通常、filenotfoundexceptionでキャッチすることはできません。

python: can't open file 'py2.py': [Errno 2] No such file or directory

事実、これに対するより良い解決策は、ファイル/スクリプトが存在するかどうかを確認してから、ファイル/スクリプトを実行することです

8
ravi.zombie

Python 3.5以降、- subprocess.check_output() よりも subprocess.run() が推奨されます。

>>> subprocess.run(['cat','/tmp/text.txt'], stdout=subprocess.PIPE).stdout
b'First line\nSecond line\n'

上記の代わりにPython 3.7以降、capture_output=trueパラメーターを使用してstdoutとstderrをキャプチャできます。

>>> subprocess.run(['cat','/tmp/text.txt'], capture_output=True).stdout
b'First line\nSecond line\n'

また、バイナリの代わりにPython 3.7 universal_newlines=True以降のテキストを操作するために、text=Trueまたはその同等物を使用することもできます。

>>> stdout = subprocess.run(['cat', '/tmp/text.txt'], capture_output=True, text=True).stdout
>>> print(stdout)
First line
Second line

詳細については、 subprocess.run() documentationを参照してください。

2
Gohu