为何Python的subprocess模块返回非预期值?代码问题求解
问题分析与解决方案
嗨,这问题我之前也碰到过,咱们一步步拆解来看:
1. 为什么python --version的输出在err里?
这不是你的代码或者subprocess模块的问题,而是Python本身的设计:python --version(以及python -V)会把版本信息输出到标准错误流(stderr),而非标准输出流(stdout)。
很多命令都会这么做——把“程序运行的核心结果”放到stdout,而版本信息、警告、提示这类“辅助信息”放到stderr,这样当你把命令的stdout重定向到文件时,不会把版本信息也混进去,保证输出的纯净性。所以你的代码里out为空、err拿到版本信息是完全正常的。
2. subprocess模块只能处理基础系统命令吗?
当然不是!subprocess是Python用来创建子进程、执行任何外部可执行程序的工具,不管是系统自带的ls、cp这类基础命令,还是你自己写的Python脚本、Go编译的二进制程序、甚至复杂的流水线命令(比如ls | grep .py,不过要注意用shell=True或者手动处理管道),它都能处理。它的能力和命令的“基础/复杂”无关,只要是能在终端执行的程序,subprocess都能调用。
怎么修改你的代码?
根据你的需求,有几种常见的处理方式:
方式一:合并stderr和stdout
如果你想把所有输出都捕获到out里,可以在创建Popen对象时,把stderr参数设为STDOUT,这样stderr的内容会直接合并到stdout中:
from subprocess import Popen, PIPE, STDOUT import shlex def pipe(command): proc = Popen(shlex.split(command), stdout=PIPE, stderr=STDOUT) out, err = proc.communicate() print "output:", out # 现在会包含版本信息 print "errors:", err # 为空 return str(out) out = pipe('python --version') print 'pipe returned ----- %s' % out
方式二:针对性返回对应流
如果你知道某些命令的输出习惯,可以在函数里做判断,或者让函数返回两个流的内容,由调用者决定用哪个:
from subprocess import Popen, PIPE import shlex def pipe(command): proc = Popen(shlex.split(command), stdout=PIPE, stderr=PIPE) out, err = proc.communicate() print "output:", out print "errors:", err # 返回两个流的内容,调用者自行选择 return str(out), str(err) out, err = pipe('python --version') # 对于python --version,我们用err里的内容 print 'pipe returned ----- %s' % err
方式三:让函数支持自定义流捕获
更灵活的方式是让函数接受参数,指定要捕获的流:
from subprocess import Popen, PIPE, STDOUT import shlex def pipe(command, capture_stderr=False): if capture_stderr: proc = Popen(shlex.split(command), stdout=PIPE, stderr=PIPE) out, err = proc.communicate() return str(out), str(err) else: proc = Popen(shlex.split(command), stdout=PIPE, stderr=STDOUT) out, _ = proc.communicate() return str(out) # 捕获两个流 out, err = pipe('python --version', capture_stderr=True) print 'Version info from stderr: %s' % err
内容的提问来源于stack exchange,提问作者jislam
相关产品推荐
相关产品推荐

