python-3.x 子进程的输出,check_output不显示子进程是否抛出异常

bnl4lu3b  于 2023-07-01  发布在  Python
关注(0)|答案(1)|浏览(103)

bounty还有3天到期。此问题的答案有资格获得+50声望奖励。pseudodev希望引起更多关注这个问题。

我有两个简单的文件。

file1.py

import subprocess

print("Going to run file1")
print(subprocess.check_output(["python", "file2.py"]).decode("utf-8"))

file1.py

print("\n\nHELLO WORLD\n\n")
raise Exception("FOO")

在运行www.example.com时file1.py,您将不会看到“Hello World”。如果你删除了这个异常,你会看到输出。
为什么出现异常时打印被隐藏?

pcww981p

pcww981p1#

考虑这些事实:

  • check_output()需要捕获输出,因此它不会直接发送到TTY。相应地,内容仅在 * 稍后 *,即运行print()时打印。
  • 异常处理 * 在抛出异常时立即发生 *。
  • check_output(),当程序运行失败时,立即抛出异常而不是返回。函数必须返回一个值,或者抛出一个异常,它不能同时做这两件事。
  • 当运行a(b())时,b发生在a之前。在这种情况下,aprint()bsubprocess.check_output()

鉴于上述情况:当subprocess.check_output()抛出一个异常时,该异常在print()启动之前被处理;因此subprocess.check_output()从子进程stdout捕获的内容永远没有机会返回,更不用说打印了。
请注意,您仍然可以检索输出:它被附加到异常对象上。

import subprocess

# original example couldn't be run by anyone except OP
#cmd = ['python', 'file2.py']

cmd = ['sh', '-c', 'echo "output"; exit 1']

try:
    print(subprocess.check_output(cmd))
except subprocess.CalledProcessError as ex:
    print(f'Unable to run process: emitted exit status {ex.returncode}')
    print(f'...after printing output {ex.output!r}')

但是,如果您要对输出做的唯一事情是无条件地打印它,那么首先考虑根本不捕获它,并让file2.py直接写入终端(或其他继承的/原始的stdout目的地)。要做到这一点,只需切换到subprocess.run(cmd, check=True)并完全跳过print

相关问题