如何捕获子进程错误
在Python中,我运行一个用FORTRAN制作的exe程序。我使用的是subprocess
模块。这个exe程序会访问并写入几个文件。如果我把这些文件设置为只读,我在Python控制台中会看到以下的错误信息。
我尝试使用try
和except
语句来捕捉这个错误,但没有成功。我还尝试使用p.stdout.readline()
,但也没能解决问题。
有没有什么系统的方法可以捕捉到这类错误呢?
代码:
import subprocess
p = subprocess.Popen('C:\\TGSSR\\test.exe' , shell=True, stdout=subprocess.PIPE)
错误追踪信息:
forrtl: severe (9): permission to access file denied, unit 6, file C:\test\mar22_SSOUT\RawReadLog.dat
Image PC Routine Line Source
test.exe 0116DC40 Unknown Unknown Unknown
test.exe 0113D42F Unknown Unknown Unknown
test.exe 0112AE97 Unknown Unknown Unknown
test.exe 0112A1DA Unknown Unknown Unknown
test.exe 0110D746 Unknown Unknown Unknown
test.exe 0108B9AC Unknown Unknown Unknown
test.exe 01173FE3 Unknown Unknown Unknown
test.exe 011588F5 Unknown Unknown Unknown
kernel32.dll 76D33677 Unknown Unknown Unknown
ntdll.dll 77A39F42 Unknown Unknown Unknown
ntdll.dll 77A39F15 Unknown Unknown Unknown
4 个回答
0
在大多数情况下,你需要使用subprocess.run这个功能。要捕捉到错误信息,你需要加上参数“capture_output=True, check=True”。
其中,check=True是非常重要的。
try:
subprocess.run(args, cwd, capture_output=True, check=True)
except subprocess.CalledProcessError as e:
print("Error while executing YoloV5:")
for k, v in e.__dict__.items():
print(k)
if isinstance(v, bytes):
print(v.decode("utf-8"))
else:
print(v)
raise Exception("Error in subcommand")
2
如果你不需要Popen的所有功能,只是想获取标准输出(stdout),你可以使用下面的方法:
try:
output = subprocess.check_output('C:\\TGSSR\\test.exe')
except subprocess.CalledProcessError as e:
print("Oops... returncode: " + e.returncode + ", output:\n" + e.output)
else:
print("Everything ok:\n" + output)
编辑:正如mgilson在另一个回答中提到的,这种方法在出错时需要返回一个非零的返回码。如果不是这样的话,你可以尝试类似下面的方式:
output = subprocess.check_output('C:\\TGSSR\\test.exe')
if "permission to access file denied" in output:
print("Failed")
使用一些只有在出错时才会出现在标准输出中的字符串
3
Python 3.5 引入了 subprocess.run()
这个方法。
这里是 @kirbyfan64sos 的答案,适用于 Python 版本大于等于 3.5:
运行这个进程:
p = subprocess.run(['C:\\TGSSR\\test.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
在版本大于等于 3.5 的情况下,你可以获取到执行进程的 returncode
(返回码)、stdout
(标准输出)和 stderr
(标准错误输出)。
如果想捕获错误信息:
stdout = p.stdout # stdout = normal output
stderr = p.stderr # stderr = error output
检查进程的返回码:
if p.returncode != 0:
# handle error
8
运行这个过程:
p = subprocess.Popen(['C:\\TGSSR\\test.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# shell = True is not needed
为了捕捉错误信息:
stdout, stderr = p.communicate()
# stdout = normal output
# stderr = error output
检查这个过程的返回代码:
if p.returncode != 0:
# handle error