Python 子进程 check_call,失败时打印 STDERR 的原生方式?
Python subprocess check_call, native way to print STDERR if it fails?
我经常希望执行 subprocess.check_output
的操作,即实时打印 STDOUT,并在退出时检查 return 代码是否为 0。但是,如果出现错误,我希望打印 STDERR。查看日志文件时,只看到 return 代码通常不是很有用。
例如:
subprocess.check_call(['ping', '-c', '1', 'github.com2'])
会产生这个错误:
subprocess.CalledProcessError: Command '['ping', '-c', '1', 'github.com2']' returned non-zero exit status 2.
这里我们想知道为什么它失败了,在现实世界的例子中,能够看到实际错误是什么变得至关重要。所以我发现我总是必须将这样的调用包装成这样才能看到 STDERR:
import subprocess
cmds = ['ping', '-c', '1', 'github.com2']
result = subprocess.run(cmds, stderr=subprocess.PIPE)
if result.returncode != 0:
msg = result.stderr.decode().strip()
raise subprocess.CalledProcessError(f"CALLED SUBPROCESS ERROR: Command: {' '.join(cmds)}\nReturn code {result.returncode}\nSTDERR: {msg}\n")
通过以上可以看出STDERR是:
ping: github.com2: Temporary failure in name resolution
我觉得一定有一个使用子进程的内置方式,但我想不通。
我猜这是不可能的,因为 CalledSubprocessError 不使用 STDERR 是异常的字符串版本:
class CalledProcessError(SubprocessError):
"""Raised when run() is called with check=True and the process
returns a non-zero exit status.
Attributes:
cmd, returncode, stdout, stderr, output
"""
def __init__(self, returncode, cmd, output=None, stderr=None):
self.returncode = returncode
self.cmd = cmd
self.output = output
self.stderr = stderr
def __str__(self):
if self.returncode and self.returncode < 0:
try:
return "Command '%s' died with %r." % (
self.cmd, signal.Signals(-self.returncode))
except ValueError:
return "Command '%s' died with unknown signal %d." % (
self.cmd, -self.returncode)
else:
return "Command '%s' returned non-zero exit status %d." % (
self.cmd, self.returncode)
@property
def stdout(self):
"""Alias for output attribute, to match stderr"""
return self.output
@stdout.setter
def stdout(self, value):
# There's no obvious reason to set this, but allow it anyway so
# .stdout is a transparent alias for .output
self.output = value
调用 subprocess.run(..., check=True)
应该会提供所有需要的信息。来自 manual:“如果检查为真,并且进程以 non-zero 退出代码退出,将引发 CalledProcessError 异常。该异常的属性保持参数、退出代码以及标准输出和标准错误 如果它们被捕获。
我经常希望执行 subprocess.check_output
的操作,即实时打印 STDOUT,并在退出时检查 return 代码是否为 0。但是,如果出现错误,我希望打印 STDERR。查看日志文件时,只看到 return 代码通常不是很有用。
例如:
subprocess.check_call(['ping', '-c', '1', 'github.com2'])
会产生这个错误:
subprocess.CalledProcessError: Command '['ping', '-c', '1', 'github.com2']' returned non-zero exit status 2.
这里我们想知道为什么它失败了,在现实世界的例子中,能够看到实际错误是什么变得至关重要。所以我发现我总是必须将这样的调用包装成这样才能看到 STDERR:
import subprocess
cmds = ['ping', '-c', '1', 'github.com2']
result = subprocess.run(cmds, stderr=subprocess.PIPE)
if result.returncode != 0:
msg = result.stderr.decode().strip()
raise subprocess.CalledProcessError(f"CALLED SUBPROCESS ERROR: Command: {' '.join(cmds)}\nReturn code {result.returncode}\nSTDERR: {msg}\n")
通过以上可以看出STDERR是:
ping: github.com2: Temporary failure in name resolution
我觉得一定有一个使用子进程的内置方式,但我想不通。
我猜这是不可能的,因为 CalledSubprocessError 不使用 STDERR 是异常的字符串版本:
class CalledProcessError(SubprocessError):
"""Raised when run() is called with check=True and the process
returns a non-zero exit status.
Attributes:
cmd, returncode, stdout, stderr, output
"""
def __init__(self, returncode, cmd, output=None, stderr=None):
self.returncode = returncode
self.cmd = cmd
self.output = output
self.stderr = stderr
def __str__(self):
if self.returncode and self.returncode < 0:
try:
return "Command '%s' died with %r." % (
self.cmd, signal.Signals(-self.returncode))
except ValueError:
return "Command '%s' died with unknown signal %d." % (
self.cmd, -self.returncode)
else:
return "Command '%s' returned non-zero exit status %d." % (
self.cmd, self.returncode)
@property
def stdout(self):
"""Alias for output attribute, to match stderr"""
return self.output
@stdout.setter
def stdout(self, value):
# There's no obvious reason to set this, but allow it anyway so
# .stdout is a transparent alias for .output
self.output = value
调用 subprocess.run(..., check=True)
应该会提供所有需要的信息。来自 manual:“如果检查为真,并且进程以 non-zero 退出代码退出,将引发 CalledProcessError 异常。该异常的属性保持参数、退出代码以及标准输出和标准错误 如果它们被捕获。