81

subprocess によって提供される関数 (call、check_call、check_output) を読み、それぞれがどのように機能し、機能が互いに異なるかを理解しました。私は現在 check_output を使用しているため、stdout にアクセスでき、次のように「try ブロック」を使用して例外をキャッチできます。

# "cmnd" is a string that contains the command along with it's arguments. 
try:
    cmnd_output = check_output(cmnd, stderr=STDOUT, shell=True, timeout=3, universal_newlines=True);                         
except CalledProcessError:                                                                                                   
    print("Status : FAIL")                                                                                                   
print("Output: \n{}\n".format(cmnd_output))                                                                                  

私が直面している問題は、例外がスローされ、「cmnd_output」が初期化されておらず、stderr にアクセスできない場合であり、次のエラー メッセージが表示されます。

print("Output: \n{}\n".format(cmnd_output))
UnboundLocalError: local variable 'cmnd_output' referenced before assignment

これは、例外により、try ブロックで「cmnd_output」への割り当てなど、それ以上の処理を行わずに「check_output」がすぐに保釈されるためだと思います。間違っている場合は修正してください。

stderr にアクセスして (stout に送信されても​​問題ありません)、終了コードにアクセスする方法はありますか。例外がスローされることなく、終了コードに基づいて合格/不合格を手動でチェックできます。

ありがとう、アーメド。

4

5 に答える 5

124

このバージョンを試してください:

import subprocess
try:
    output = subprocess.check_output(
        cmnd, stderr=subprocess.STDOUT, shell=True, timeout=3,
        universal_newlines=True)
except subprocess.CalledProcessError as exc:
    print("Status : FAIL", exc.returncode, exc.output)
else:
    print("Output: \n{}\n".format(output))

このようにして、呼び出しが成功した場合にのみ出力を印刷します。の場合はCalledProcessError、リターン コードと出力を出力します。

于 2013-04-24T17:38:26.783 に答える
74

stdout受け入れられた解決策は、とを混在させても問題ない場合をカバーしますがstderr、子プロセスが (何らかの理由で)失敗しない出力 (つまり、重大ではない警告を出力する) のためにstderrIN ADDITION を使用することを決定した場合、stdout与えられた解決策は望ましくないかもしれません。

たとえば、JSON への変換など、出力に対して追加の処理を行う予定でstderrstderr.

その場合、次のことが機能することがわかりました。

cmd_args = ... what you want to execute ...

pipes = subprocess.Popen(cmd_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
#If you are using python 2.x, you need to include shell=True in the above line
std_out, std_err = pipes.communicate()

if pipes.returncode != 0:
    # an error happened!
    err_msg = "%s. Code: %s" % (std_err.strip(), pipes.returncode)
    raise Exception(err_msg)

elif len(std_err):
    # return code is 0 (no error), but we may want to
    # do something with the info on std_err
    # i.e. logger.warning(std_err)

# do whatever you want with std_out
# i.e. json.loads(std_out)
于 2014-12-26T20:09:57.750 に答える
15

提案されたソリューションはどちらも、stdout/stderr を混在させるか、.NETPopenほど単純ではないものを使用しcheck_outputます。ただし、パイプを使用してstderr を単純にキャプチャするcheck_output場合は、同じことを達成し、stdout/stderr を分離したままにすることができます。

import sys
import subprocess

try:
    subprocess.check_output(cmnd, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
    print('exit code: {}'.format(e.returncode))
    print('stdout: {}'.format(e.output.decode(sys.getfilesystemencoding())))
    print('stderr: {}'.format(e.stderr.decode(sys.getfilesystemencoding())))

この例では、stderr をキャプチャしたため、例外のstderr属性で使用できます (パイプでキャプチャしないと、単に になりますNone)。

于 2018-02-15T17:45:04.563 に答える
-2

try ステートメントの前に変数 cmnd_output を初期化しないのはなぜですか? そうすれば、期待どおりに機能します。次の行は機能します。try ステートメントの上に追加するだけです。

cmnd_output = ''
于 2013-04-24T17:36:22.557 に答える