如何检查子进程中的 Popen 是否引发错误

O.r*_*rka 3 python bash shell command subprocess

我正在编写一个以特定顺序使用一堆 bash 调用的管道。

如何判断我的命令是否引发错误?

例如,我正在运行一个带有子进程的 Java 程序,当这个进程出错时它不会警告我或退出。

subprocess我的process对象中或对象中是否有具有此实用程序的东西?

process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process.wait()
Run Code Online (Sandbox Code Playgroud)

当我尝试来自Python的建议:“subprocess.Popen”检查成功和错误时,我收到以下错误:

process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process.wait()
Run Code Online (Sandbox Code Playgroud)

Jam*_*mes 7

双方check_callcheck_output应传递命令的列表由指挥系统(即会被发送到相同的命令列表中运行Popen)。这两个都是阻塞调用,这意味着 Python 将等到它们完成运行更多代码。

UsingPopen将命令列表发送到命令系统,但不会阻止 Python 代码的进一步执行。您可以使用对象的.poll方法检查进程Popen,或者您可以使用.communicate它将返回标准输出和标准错误流的元组进行阻塞调用。

假设你想要执行命令的结果,并且命令会正确地向错误流报告错误,你可以使用:

process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()

if err:
     print('The process raised an error:', err.decode())
Run Code Online (Sandbox Code Playgroud)

这里有些例子:

使用Popen

import subprocess

# first a command that works correctly
proc = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
if not err:
    print('--No errors--\n', out.decode())
else:
    print('--Error--\n', err.decode())

# prints:
--No errors--
anaconda3
Desktop
Documents
Downloads

# next a command, which generates an error. The `-w` switch is invalid
proc = subprocess.Popen(['ls', '-w'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
if not err:
    print('--No errors--\n', out.decode())
else:
    print('--Error--\n', err.decode())

# prints:
--Error--
 ls: option requires an argument -- 'w'
Try 'ls --help' for more information.
Run Code Online (Sandbox Code Playgroud)

使用 check_call

check_call 如果来自命令系统的返回码不是 0,则会引发 Python 异常。

# first with a working command:
ret_code = subprocess.check_call(['ls', '-a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
ret_code
# returns:
0

# and now with the command that generates an error:
ret_code = subprocess.check_call(['ls', '-w'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

# raises an exception:
---------------------------------------------------------------------------
CalledProcessError                        Traceback (most recent call last)
<ipython-input-25-3cd5107991a2> in <module>()
----> 1 ret_code = subprocess.check_call(['ls', '-w'], stdout=subprocess.PIPE, 
        stderr=subprocess.PIPE)

~/anaconda3/lib/python3.6/subprocess.py in check_call(*popenargs, **kwargs)
    289         if cmd is None:
    290             cmd = popenargs[0]
--> 291         raise CalledProcessError(retcode, cmd)
    292     return 0
    293

CalledProcessError: Command '['ls', '-w']' returned non-zero exit status 2.
Run Code Online (Sandbox Code Playgroud)

要处理异常,请使用try/except块。

try:
    ret_code = subprocess.check_call(['ls', '-w'], stdout=subprocess.PIPE, 
        stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
    ret_code = e.returncode
    print('An error occurred.  Error code:', ret_code)

# prints:
An error occurred.  Error code: 2
Run Code Online (Sandbox Code Playgroud)

使用 check_output

check_output非常相似,check_call如果来自命令系统的返回码不是 0,它将引发 Python 异常。但是,如果返回码为 0,它将返回标准输出流中的输出。

# just with the error process this time
try:
    ret_code = subprocess.check_output(['ls', '-w'], stdout=subprocess.PIPE, 
        stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
    ret_code = e.returncode
    print('An error occurred.  Error code:', ret_code)

# prints:
An error occurred.  Error code: 2
Run Code Online (Sandbox Code Playgroud)