当我将子进程与 check=True 一起使用时,如何获得错误消息
How can I get error messages when I use subprocess with check=True
我刚刚意识到如果我在子进程中使用 check=True,我不会得到 CompletedProcess
描述符。这看起来像是一个设计缺陷:如何获取被调用程序发送的错误消息?
显然还有其他方法可以获取我程序的 return 代码,但这里的重点是 check=True 参数似乎与错误处理不兼容。
还是我漏掉了什么?
#!/usr/bin/python3
import subprocess
import sys
subproc1 = subprocess.run('ls /nonexistent', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True)
print(subproc1.stderr, file=sys.stderr, end='', flush=True)
print(subproc1.stdout, file=sys.stdout, end='', flush=True)
print('▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔', file=sys.stderr, flush=True)
try: subproc2 = subprocess.run('ls /', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True, check=True)
except subprocess.CalledProcessError:
print("FAIL")
print(subproc2.stderr, file=sys.stderr, end='', flush=True)
print(subproc2.stdout, file=sys.stdout, end='', flush=True)
print('▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔', file=sys.stderr, flush=True)
raise
else:
print("GOOD")
print(subproc2.stderr, file=sys.stderr, end='', flush=True)
print(subproc2.stdout, file=sys.stdout, end='', flush=True)
print('▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔', file=sys.stderr, flush=True)
try: subproc3 = subprocess.run('ls /nonexistent', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True, check=True)
except subprocess.CalledProcessError:
print("FAIL")
print(subproc3.stderr, file=sys.stderr, end='', flush=True)
print(subproc3.stdout, file=sys.stdout, end='', flush=True)
print('▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔', file=sys.stderr, flush=True)
raise
else:
print("GOOD")
print(subproc3.stderr, file=sys.stderr, end='', flush=True)
print(subproc3.stdout, file=sys.stdout, end='', flush=True)
print('▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔', file=sys.stderr, flush=True)
产量:
ls: cannot access '/nonexistent': No such file or directory
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
GOOD
bin
[...]
var
vmlinuz
vmlinuz.old
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
FAIL
Traceback (most recent call last):
File "/root/subprocess_error.py", line 27, in <module>
try: subproc3 = subprocess.run('ls /nonexistent', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True, check=True)
File "/usr/lib/python3.7/subprocess.py", line 487, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'ls /nonexistent' returned non-zero exit status 2.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/root/subprocess_error.py", line 30, in <module>
print(subproc3.stderr, file=sys.stderr, end='', flush=True)
NameError: name 'subproc3' is not defined
捕获的内容保存到异常本身。
将异常对象分配给一个变量,并从中读取 .stdout
和 .stderr
。
import subprocess
import sys
try:
subproc3 = subprocess.run('ls /nonexistent', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True, check=True)
except subprocess.CalledProcessError as ex:
print("FAIL")
print(ex.stderr, file=sys.stderr, end='', flush=True)
print(ex.stdout, file=sys.stdout, end='', flush=True)
我刚刚意识到如果我在子进程中使用 check=True,我不会得到 CompletedProcess
描述符。这看起来像是一个设计缺陷:如何获取被调用程序发送的错误消息?
显然还有其他方法可以获取我程序的 return 代码,但这里的重点是 check=True 参数似乎与错误处理不兼容。
还是我漏掉了什么?
#!/usr/bin/python3
import subprocess
import sys
subproc1 = subprocess.run('ls /nonexistent', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True)
print(subproc1.stderr, file=sys.stderr, end='', flush=True)
print(subproc1.stdout, file=sys.stdout, end='', flush=True)
print('▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔', file=sys.stderr, flush=True)
try: subproc2 = subprocess.run('ls /', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True, check=True)
except subprocess.CalledProcessError:
print("FAIL")
print(subproc2.stderr, file=sys.stderr, end='', flush=True)
print(subproc2.stdout, file=sys.stdout, end='', flush=True)
print('▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔', file=sys.stderr, flush=True)
raise
else:
print("GOOD")
print(subproc2.stderr, file=sys.stderr, end='', flush=True)
print(subproc2.stdout, file=sys.stdout, end='', flush=True)
print('▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔', file=sys.stderr, flush=True)
try: subproc3 = subprocess.run('ls /nonexistent', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True, check=True)
except subprocess.CalledProcessError:
print("FAIL")
print(subproc3.stderr, file=sys.stderr, end='', flush=True)
print(subproc3.stdout, file=sys.stdout, end='', flush=True)
print('▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔', file=sys.stderr, flush=True)
raise
else:
print("GOOD")
print(subproc3.stderr, file=sys.stderr, end='', flush=True)
print(subproc3.stdout, file=sys.stdout, end='', flush=True)
print('▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔', file=sys.stderr, flush=True)
产量:
ls: cannot access '/nonexistent': No such file or directory
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
GOOD
bin
[...]
var
vmlinuz
vmlinuz.old
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
FAIL
Traceback (most recent call last):
File "/root/subprocess_error.py", line 27, in <module>
try: subproc3 = subprocess.run('ls /nonexistent', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True, check=True)
File "/usr/lib/python3.7/subprocess.py", line 487, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'ls /nonexistent' returned non-zero exit status 2.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/root/subprocess_error.py", line 30, in <module>
print(subproc3.stderr, file=sys.stderr, end='', flush=True)
NameError: name 'subproc3' is not defined
捕获的内容保存到异常本身。
将异常对象分配给一个变量,并从中读取 .stdout
和 .stderr
。
import subprocess
import sys
try:
subproc3 = subprocess.run('ls /nonexistent', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True, check=True)
except subprocess.CalledProcessError as ex:
print("FAIL")
print(ex.stderr, file=sys.stderr, end='', flush=True)
print(ex.stdout, file=sys.stdout, end='', flush=True)