Python “subprocess.Popen” - 检查成功和错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25079140/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 19:42:05  来源:igfitidea点击:

"subprocess.Popen" - checking for success and errors

pythonpython-3.xsubprocessstdoutstderr

提问by Zingam

I want to check if a subprocess has finished execution successfully or failed. Currently I have come up with a solution but I am not sure if it is correct and reliable. Is it guaranteed that every process outputs its errors only to stderr respectfully to stdout:

我想检查一个子流程是否成功完成执行或失败。目前我已经提出了一个解决方案,但我不确定它是否正确和可靠。是否保证每个进程仅将其错误输出到 stderr 尊重stdout

Note: I am not interested in just redirecting/printing out the output. That I know already how to do.

注意:我对重定向/打印输出不感兴趣。我已经知道该怎么做了。

pipe = subprocess.Popen(command,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                universal_newlines=True)

if "" == pipe.stdout.readline():
    print("Success")
    self.isCommandExectutionSuccessful = True

if not "" == pipe.stderr.readline():
    print("Error")
    self.isCommandExectutionSuccessful = True

alternatively:

或者:

   if "" == pipe.stdout.readline():
       print("Success")
       self.isCommandExectutionSuccessful = True
   else:
       print("Error")
       self.isCommandExectutionSuccessful = False

and:

和:

   if not "" == pipe.stderr.readline():
       print("Success")
       self.isCommandExectutionSuccessful = True
   else:
       print("Error")
       self.isCommandExectutionSuccessful = False

采纳答案by elParaguayo

Do you need to do anything with the output of the process?

您需要对流程的输出做些什么吗?

The check_callmethod might be useful here. See the python docs here: https://docs.python.org/2/library/subprocess.html#subprocess.check_call

check_call方法可能在这里有用。在此处查看 python 文档:https: //docs.python.org/2/library/subprocess.html#subprocess.check_call

You can then use this as follows:

然后,您可以按如下方式使用它:

try:
  subprocess.check_call(command)
except subprocess.CalledProcessError:
  # There was an error - command exited with non-zero code

However, this relies on commandreturning an exit code of 0 for succesful completion and a non-zero value for an error.

但是,这依赖于command返回退出代码 0 以表示成功完成和返回非零值表示错误。

If you need to capture the output as well, then the check_outputmethod may be more appropriate. It is still possible to redirect the standard error if you need this as well.

如果您还需要捕获输出,那么该check_output方法可能更合适。如果您也需要,仍然可以重定向标准错误。

try:
  proc = subprocess.check_output(command, stderr=subprocess.STDOUT)
  # do something with output
except subprocess.CalledProcessError:
  # There was an error - command exited with non-zero code

See the docs here: https://docs.python.org/2/library/subprocess.html#subprocess.check_output

请参阅此处的文档:https: //docs.python.org/2/library/subprocess.html#subprocess.check_output

回答by vks

      output,error=pipe.communicate()

This will wait for command to finish and give you output or error depending on the state of command.

这将等待命令完成并根据命令的状态为您提供输出或错误。

回答by Alexey Bureev

You can check return code of the process using check_call() method. In case if process returned non-zero value CalledProcessError will be raised.

您可以使用 check_call() 方法检查进程的返回代码。如果进程返回非零值 CalledProcessError 将被引发。

回答by Zingam

This is how I did it finally:

这就是我最终做到的:

    # Call a system process
    try:
        # universal_newlines - makes manual decoding of subprocess.stdout unnecessary
        output = subprocess.check_output(command,
                                         stderr=subprocess.STDOUT,
                                         universal_newlines=True)

        # Print out command's standard output (elegant)
        self.textEdit_CommandLineOutput.insertPlainText(output)
        self.isCommandExecutionSuccessful = True

    except subprocess.CalledProcessError as error:
        self.isCommandExecutionSuccessful = False

        errorMessage = ">>> Error while executing:\n"\
                       + command\
                       + "\n>>> Returned with error:\n"\
                       + str(error.output)
        self.textEdit_CommandLineOutput.append(errorMessage)

        QMessageBox.critical(None,
                             "ERROR",
                             errorMessage)
        print("Error: " + errorMessage)

    except FileNotFoundError as error:
        errorMessage = error.strerror
        QMessageBox.critical(None,
                             "ERROR",
                             errorMessage)
        print("Error: ", errorMessage)

I hope it will be useful to someone else.

我希望它对其他人有用。

回答by PJ_Finnegan

Complete solution with check on return code, stdout and stderr:

检查返回码、标准输出和标准错误的完整解决方案:

import subprocess as sp

# ok
pipe = sp.Popen( 'ls /bin', shell=True, stdout=sp.PIPE, stderr=sp.PIPE )
# res = tuple (stdout, stderr)
res = pipe.communicate()
print("retcode =", pipe.returncode)
print("res =", res)
print("stderr =", res[1])
for line in res[0].decode(encoding='utf-8').split('\n'):
  print(line)

# with error
pipe = sp.Popen( 'ls /bing', shell=True, stdout=sp.PIPE, stderr=sp.PIPE )
res = pipe.communicate()
print("retcode =", pipe.returncode)
print("res =", res)
print("stderr =", res[1])

Prints:

印刷:

retcode = 0
res = (b'bash\nbunzip2\nbusybox\nbzcat\n...zmore\nznew\n', b'')
stderr = b''
bash
bunzip2
busybox
bzcat
...
zmore
znew

retcode = 2
res = (b'', b"ls: cannot access '/bing': No such file or directory\n")
stderr = b"ls: cannot access '/bing': No such file or directory\n"