Program Tip

하위 프로세스 호출에서 종료 코드 및 stderr 가져 오기

programtip 2020. 12. 3. 19:08
반응형

하위 프로세스 호출에서 종료 코드 및 stderr 가져 오기


call, check_call, check_output과 같은 하위 프로세스에서 제공하는 기능을 읽고 각 기능이 어떻게 작동하고 서로 다른지 이해합니다. 현재 check_output을 사용하고 있으므로 다음과 같이 stdout에 액세스하고 "try block"을 사용하여 예외를 잡을 수 있습니다.

# "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

그 이유는 예외로 인해 "check_output"이 추가 처리없이 즉각 "cmnd_output"에 할당되지 않고 즉시 중단되기 때문이라고 생각합니다. try 블록에서. 내가 틀렸다면 나를 바로 잡으십시오.

stderr에 대한 액세스 권한을 얻고 (stout에 전송해도 괜찮습니다) 종료 코드에 액세스 할 수있는 방법이 있습니까? 예외가 발생하지 않고 종료 코드를 기반으로 수동으로 통과 / 실패를 확인할 수 있습니다.

고마워요, 아메드.


이 버전을 사용해보십시오 :

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당신의 경우 반환 코드와 출력을 인쇄하십시오.


허용되는 솔루션은 stdout및을 혼합하는 경우를 포함 stderr하지만 하위 프로세스 (어떤 이유로 든)가 실패하지 않은 출력 (즉, 중요하지 않은 경고를 출력 stderr하기 stdout위해)에 추가로 사용하기로 결정한 경우 주어진 솔루션이 바람직하지 않을 수 있습니다.

예를 들어 JSON으로 변환하는 것과 같이 출력에 대한 추가 처리를 수행하고를 혼합 stderr하면 출력이 추가 된 stderr출력으로 인해 순수한 JSON이 아니므로 전체 프로세스가 실패 합니다.

이 경우 작동하는 다음을 발견했습니다.

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

pipes = subprocess.Popen(cmnd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
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)

제안 된 두 솔루션 모두 stdout / stderr를 혼합하거나 사용 Popen하기가 check_output. 그러나 파이프를 사용하여 check_output단순히 stderr캡처 하는 경우 사용 하는 동안 동일한 작업을 수행하고 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).


why not initialize the varible cmnd_output before the try statement? That way it will work the way you expect it to. Following line would work, just add it above try statement :

cmnd_output = ''

참고URL : https://stackoverflow.com/questions/16198546/get-exit-code-and-stderr-from-subprocess-call

반응형