Skip to main content
 首页 » 编程设计

python之使用 Popen.communicate 时如何将警告与 stderr 中发现的错误分开

2025年05月04日31mengfanrong

我使用了 Python 的 subprocess.Popen执行命令并捕获其输出:

p = Popen(cmd, stdout=PIPE, stderr=PIPE,shell=True) 
stdout, stderr = p.communicate() 

我想使用 stderr 来告诉用户出现错误并退出我的脚本:

if stderr !='': 
    return {'error':stderr} 

但现在我发现 stderr 可以包含可以安全忽略的警告,所以我的脚本不应该退出,而是继续完成工作。

有没有办法在 stderr 中将警告与错误分开?

请您参考如下方法:

univerio 是正确的,因为您在 stderr 中发现的任何字节都没有特定含义...将其视为“标准非输出”而不是“标准错误”。但是,在大多数操作系统上,您可以使用进程的退出状态(或“返回代码”)来跳过大部分进度条和其他非错误输出。

Popen 对象有一个名为 returncode 的字段,用于存储子进程退出时返回的任何值。此值为 None,直到 1) 进程终止,以及 2) 您使用 poll 收集其退出状态。或 wait方法(至少在类 Unix 系统上)。由于您使用的是 communicate ,它总是同时执行 1 和 2,p.returncode 在您关心它时应该始终是一个整数。

作为一般规则,0 退出状态表示成功,而任何其他值表示失败。如果您相信您调用的程序会返回正确的值,您可以使用它来跳过 stderr 上的大部分垃圾输出:

# ...same as before... 
stdout, stderr = p.communicate() 
if p.returncode and stderr: 
    return {'error': stderr} 

如果在 stderr 中找到的字节不够重要,不足以产生非 0 退出状态,那么它们也不够重要,您无法报告。

要对此进行测试,您可以编写一些产生stderr 输出然后exit 的小脚本。 ,无论成功与否。

警告.py:

import sys 
print('This is spam on stderr.', file=sys.stderr) 
sys.exit(0) 

errors.py:

import sys 
print('This is a real error message.', file=sys.stderr) 
sys.exit(1) 

这仍然留下了将旋转警棍和其他进度报告垃圾邮件与实际错误消息分开的任务,但您只需为失败的进程执行此操作......甚至可能不会,因为“未死”然而!”在这些情况下,消息实际上可能很有用。

PS:在 Python 3 中,stdout 和 stderr 将是 bytes 对象,因此您需要 decode在像字符串一样对待它们之前。