[英]How to catch the errors of a child process using Python subprocess?
I have the following Python(2.7) code:我有以下 Python(2.7) 代码:
try:
FNULL = open(os.devnull,'w')
subprocess.check_call(["tar", "-czvf", '/folder/archive.tar.gz', '/folder/some_other_folder'], stdout=FNULL, stderr=subprocess.STDOUT)
except Exception as e:
print str(e)
The problem which I face is that, when there is no more space for the archive, print str(e)
prints Command '['tar', '-czvf', '/folder/archive.tar.gz', '/folder/some_other_folder']' returned non-zero exit status 1
, which is true, but I want to catch the real error here, that is gzip: write error: No space left on device
(I got the this error when I ran the same tar comand manually).我面临的问题是,当存档没有更多空间时, print str(e)
打印Command '['tar', '-czvf', '/folder/archive.tar.gz', '/folder/some_other_folder']' returned non-zero exit status 1
,这是真的,但我想在这里捕获真正的错误,即gzip: write error: No space left on device
(当我运行相同的tar 命令手动)。 Is that possible somehow?这有可能吗? I assume that gzip is another process within tar.我假设 gzip 是 tar 中的另一个进程。 Am I wrong?我错了吗? Please keep in mind that upgrading to Python 3 is not possible.请记住,无法升级到 Python 3。
EDIT: I also tried to use subprocess.check_output()
and print the contents of e.output
but that also didn't work编辑:我也尝试使用e.output
subprocess.check_output()
并打印e.output
的内容,但这也不起作用
On Python 3, the solution is simple, and you should be using Python 3 for new code anyway (Python 2.7 ended all support nearly a year ago):在 Python 3 上,解决方案很简单,无论如何你应该使用 Python 3 来编写新代码(Python 2.7 几乎在一年前结束了所有支持):
The problem is that the program is echoing the error to stderr
, so check_output
doesn't capture it (either normally, or in the CalledProcessError
).问题是程序将错误回显到stderr
,因此check_output
不会捕获它(通常或在CalledProcessError
)。 The best solution is to use subprocess.run
(which check_call
/ check_output
are just a thin wrapper over) and ensure you capture both stdout
and stderr
.最好的解决办法是使用subprocess.run
(其中check_call
/ check_output
只是一个瘦包装过),并确保你同时捕获stdout
和stderr
。 The simplest approach is:最简单的方法是:
try:
subprocess.run(["tar", "-czvf", '/folder/archive.tar.gz', '/folder/some_other_folder'],
check=True, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
# ^ Ignores stdout ^ Captures stderr so e.stderr is populated if needed
except CalledProcessError as e:
print("tar exited with exit status {}:".format(e.returncode), e.stderr, file=sys.stderr)
If you must do this on Python 2, you have to handle it all yourself by manually invoking Popen
, as none of the high level functions available there will cover you ( CalledProcessError
didn't spawn a stderr
attribute until 3.5, because no high-level API that raised it was designed to handle stderr
at all):如果您必须在 Python 2 上执行此操作,则必须通过手动调用Popen
自己处理这一切,因为那里可用的任何高级函数都不会覆盖您( CalledProcessError
直到 3.5 才产生stderr
属性,因为没有高级函数提出它的 API 旨在完全处理stderr
):
with open(os.devnull, 'wb') as f:
proc = subprocess.Popen(["tar", "-czvf", '/folder/archive.tar.gz', '/folder/some_other_folder'],
stdout=f, stderr=subprocess.PIPE)
_, stderr = proc.communicate()
if proc.returncode != 0:
# Assumes from __future__ import print_function at top of file
# because Python 2 print statements are terrible
print("tar exited with exit status {}:".format(proc.returncode), stderr, file=sys.stderr)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.