Python3 subprocess.Popen中stdout与stderr输出错位问题及规范处理方法咨询
如何处理subprocess中stdout与stderr错位的问题?
我正尝试用Python3的subprocess模块中的Popen命令编写脚本,获取部分已安装软件的版本信息,示例代码如下:
from subprocess import Popen, PIPE nginx_version, err = Popen(["nginx", "-v"], stdout=PIPE, stderr=PIPE).communicate() print("Nginx Version:" + nginx_version.decode("utf-8")) print("Stderr:" + err.decode("utf-8"))
实际运行后输出如下:
Nginx Version: Stderr: nginx version: nginx/1.16.1
可以看到Nginx的版本信息并没有输出到预期的stdout,而是跑到了stderr中,出现了stdout与stderr值不匹配的情况。请问是否存在标准的方法来处理这种问题?
你遇到的这个情况其实挺常见的——很多命令行工具并没有严格遵循「业务输出走stdout、辅助提示走stderr」的约定,像nginx的-v就特意把版本信息输出到了stderr里(可能是认为版本提示属于非业务性的辅助信息)。针对这种stdout和stderr错位的问题,有几种标准的处理方式:
1. 合并两个输出流,统一处理
如果不关心内容到底来自stdout还是stderr,只想拿到版本信息,最简单的方式就是把stderr重定向到stdout,这样两个流的内容会合并到一起:
from subprocess import Popen, PIPE, STDOUT proc = Popen(["nginx", "-v"], stdout=PIPE, stderr=STDOUT) output, _ = proc.communicate() # 用strip()去掉多余的换行符和空白 print("Nginx Version:" + output.decode("utf-8").strip())
这种方式适合大多数场景,不需要纠结输出到底走哪个流,只要拿到有效内容就行。
2. 双流捕获,兜底处理
如果需要保留区分两个流的能力,但又要应对这种错位情况,可以先检查stdout是否为空,为空的话就用stderr的内容作为兜底:
from subprocess import Popen, PIPE nginx_version, err = Popen(["nginx", "-v"], stdout=PIPE, stderr=PIPE).communicate() # 先处理输出,去除多余空白字符 stdout_content = nginx_version.decode("utf-8").strip() stderr_content = err.decode("utf-8").strip() # 优先取stdout,为空则用stderr的内容 version_output = stdout_content if stdout_content else stderr_content print("Nginx Version:" + version_output)
这种方式灵活性更高,适合你不确定目标工具输出位置的场景。
3. 针对性适配已知工具的行为
如果是你熟悉的工具,比如nginx,其实可以提前查它的文档:nginx的-v确实输出到stderr,而大写的-V会输出包含配置参数的详细版本信息到stdout。这种情况下,你可以直接针对性读取对应的流:
from subprocess import Popen, PIPE # 直接读取stderr的版本信息 _, err = Popen(["nginx", "-v"], stdout=PIPE, stderr=PIPE).communicate() print("Nginx Version:" + err.decode("utf-8").strip()) # 或者用大写-V读取stdout的详细配置版本信息 nginx_detail, _ = Popen(["nginx", "-V"], stdout=PIPE, stderr=PIPE).communicate() print("Nginx Detail:" + nginx_detail.decode("utf-8").strip())
这种方式最直接高效,前提是你了解目标工具的输出规则。
内容的提问来源于stack exchange,提问作者Atharva Kale
相关产品推荐
相关产品推荐

