Python 如何捕获子流程错误

Python 如何捕获子流程错误,python,subprocess,Python,Subprocess,在Python中,我运行使用FORTRAN生成的exe。我使用子流程模块。exe访问和写入多个文件。如果我将这些文件设置为只读,我会在Python控制台中看到以下跟踪 我尝试使用try,除了语句。但我无法捕捉到错误。我还尝试使用p.stdout.readline()。但没有成功 有没有一种系统的方法来捕捉这种错误 代码: 回溯: forrtl: severe (9): permission to access file denied, unit 6, file C:\test\mar22_SSO

在Python中,我运行使用FORTRAN生成的exe。我使用
子流程
模块。exe访问和写入多个文件。如果我将这些文件设置为只读,我会在Python控制台中看到以下跟踪

我尝试使用
try
除了
语句。但我无法捕捉到错误。我还尝试使用
p.stdout.readline()
。但没有成功

有没有一种系统的方法来捕捉这种错误

代码:

回溯:

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
运行流程:

p = subprocess.Popen(['C:\\TGSSR\\test.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# shell = True is not needed
p = subprocess.run(['C:\\TGSSR\\test.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
要捕获错误消息,请执行以下操作:

stdout, stderr = p.communicate()
# stdout = normal output
# stderr = error output
stdout = p.stdout # stdout = normal output
stderr = p.stderr # stderr = error output
检查流程返回代码:

if p.returncode != 0:
    # handle error
if p.returncode != 0:
# handle error

如果不需要Popen的所有功能,只需要获取标准输出,您还可以选择:

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")
Python 3.5引入了一些字符串,这些字符串仅在出现错误时才会出现在标准输出上

以下是针对Python>=3.5更新的@kirbyfan64sos答案:

运行流程:

p = subprocess.Popen(['C:\\TGSSR\\test.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# shell = True is not needed
p = subprocess.run(['C:\\TGSSR\\test.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
在>=3.5中,您可以从执行的进程访问
returncode
stdout
stderr

要捕获错误消息,请执行以下操作:

stdout, stderr = p.communicate()
# stdout = normal output
# stderr = error output
stdout = p.stdout # stdout = normal output
stderr = p.stderr # stderr = error output
检查流程返回代码:

if p.returncode != 0:
    # handle error
if p.returncode != 0:
# handle error

虽然在windows上可能不需要,但如果不打算使用shell,则应将可执行文件作为列表传递:
['C:\\TGSSR\\test.ext']
。此外,返回代码可能不可靠,因为(据我所知),仍然没有一种很好的标准化方法在Fortran中设置进程的返回代码。在这种情况下,p在两种状态下都为null(成功或失败)。所以我不能依赖它@mgilson:
Popen(“程序”)
有效。它相当于POSIX上的
Popen([“程序”])
。在Windows上,字符串参数始终有效。@user3161836:
p
不为空;您的意思可能是
p.returncode是None
。后者意味着这一过程尚未完成。你应该在
p.communicate()
returns(它等待过程完成)之后检查
p.returncode
。@mgilson:我真的忘了。谢谢你指出这一点。它应该是
子进程。在这种情况下称为“进程错误”
。如果我只需要运行exe,我想我可以选择此选项。如果我这样做,我会弄错任何主要功能吗?这可能是措词不当,check_output是一个基于Popen的方便函数,它不需要自己处理stdout/stderr(在你的第一篇文章中,你实际上至少需要一个p.communicate()为了防止标准管道缓冲区完全填满(如果您使用FORTRAN工具输出了大量数据,这将有效地暂停执行)。不过,您可以轻松切换到Popen。Popen提供了更细粒度的进程创建控制:无关:为了避免转义反斜杠,可以使用原始字符串文本:
r'C:\TGSSR\test.exe'
。不要在Windows上使用
shell=True
,除非您使用shell功能,例如调用内置shell命令,如
dir
。不要使用
stdout=PIPE
,除非您稍后阅读
p.stdout
谢谢您的评论!有时,错误会写入stdout/stderr之外(直接写入终端)。看见