如何使用 Python 子进程捕获子进程的错误?
How to catch the errors of a child process using Python subprocess?
我有以下 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)
我面临的问题是,当存档不再有 space 时,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 命令时,我得到了这个错误)。这有可能吗?我假设 gzip 是 tar 中的另一个进程。我错了吗?请记住,升级到 Python 3 是不可能的。
编辑:我也尝试使用 subprocess.check_output()
并打印 e.output
的内容,但这也没有用
Python 3 种适合正常人的解决方案
在 Python 3 上,解决方案很简单,无论如何你都应该使用 Python 3 来编写新代码(Python 2.7 在将近一年前结束了所有支持):
问题是程序将错误回显到 stderr
,因此 check_output
没有捕获它(通常,或在 CalledProcessError
中)。最好的解决方案是使用 subprocess.run
(check_call
/check_output
只是一个薄包装)并确保您同时捕获 stdout
和 stderr
。最简单的方法是:
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)
Python 2 为喜欢不受支持的软件的人提供的解决方案
如果您 必须 在 Python 2 上执行此操作,则您必须通过手动调用 Popen
自行处理这一切,因为 none那里可用的高级功能的一部分将覆盖你(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)
我有以下 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)
我面临的问题是,当存档不再有 space 时,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 命令时,我得到了这个错误)。这有可能吗?我假设 gzip 是 tar 中的另一个进程。我错了吗?请记住,升级到 Python 3 是不可能的。
编辑:我也尝试使用 subprocess.check_output()
并打印 e.output
的内容,但这也没有用
Python 3 种适合正常人的解决方案
在 Python 3 上,解决方案很简单,无论如何你都应该使用 Python 3 来编写新代码(Python 2.7 在将近一年前结束了所有支持):
问题是程序将错误回显到 stderr
,因此 check_output
没有捕获它(通常,或在 CalledProcessError
中)。最好的解决方案是使用 subprocess.run
(check_call
/check_output
只是一个薄包装)并确保您同时捕获 stdout
和 stderr
。最简单的方法是:
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)
Python 2 为喜欢不受支持的软件的人提供的解决方案
如果您 必须 在 Python 2 上执行此操作,则您必须通过手动调用 Popen
自行处理这一切,因为 none那里可用的高级功能的一部分将覆盖你(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)