如何捕获子进程错误

5 投票
4 回答
23844 浏览
提问于 2025-04-17 23:28

在Python中,我运行一个用FORTRAN制作的exe程序。我使用的是subprocess模块。这个exe程序会访问并写入几个文件。如果我把这些文件设置为只读,我在Python控制台中会看到以下的错误信息。

我尝试使用tryexcept语句来捕捉这个错误,但没有成功。我还尝试使用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

撰写回答