声明:这是个标题党,如果你执意想用os.popen做到控制台输出重定向,这篇文章中并没有答案,如果你对os.popen没有那么强烈的执念,请继续看
前段时间写代码使用os.popen时,遇到一个问题:执行的命令有可能会运行失败,虽然在代码中增加了异常处理,但是对于功能的要求是,不能在控制台打印出来报错信息,附上使用os.popen的情况:
# -*- coding: utf-8 -*-
import os
if __name__ == '__main__':
CMD = "adb -H 1.2.3.5 devices" # ip未知,执行肯定会报错
prco = os.popen(CMD, mode="r", buffering=-1)
outputStr = str(prco.read())
print("output: " + outputStr)
控制台输出结果是这样的:
** Cannot start server on remote host
error: can't connect to 1.2.3.5:7305: cannot connect to 1.2.3.5:7305: 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。 (10060)
output: List of devices attached
可以看到前两行输出部署预期想要的,那要怎么才能不让命令中的stderr输出到控制台呢?网上搜了下,大把的解决方法都是写个脚本,让popen调用这个脚本,然后用输出重定向的方式去解决这个问题。但是!不!够!优!雅!
有没有一种方式可以直接过滤掉stderr呢?答案是肯定的,我们可以通过subprocess.Popen方法完美解决这个问题
# -*- coding: utf-8 -*-
import subprocess
import io
if __name__ == '__main__':
CMD = "adb -H 1.2.3.5 devices" # ip未知,执行肯定会报错
proc = subprocess.Popen(CMD, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=-1)
proc.wait()
stream_stdout = io.TextIOWrapper(proc.stdout, encoding='utf-8')
stream_stderr = io.TextIOWrapper(proc.stderr, encoding='utf-8')
str_stdout = str(stream_stdout.read())
str_stderr = str(stream_stderr.read())
print("stdout: " + str_stdout)
print("stderr: " + str_stderr)
控制台输出结果:
stdout: List of devices attached
stderr: ** Cannot start server on remote host
error: can't connect to 1.2.3.5:7305: cannot connect to 1.2.3.5:7305: 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。 (10060)
这样就能捕捉并指定输出stderr的内容了,顺便说一句,这里也可以将Popen中的stderr参数值从subprocess.PIPE换成subprocess.DEVNULL,不过这样就不会得到stderr的输出了。
os.popen和subprocess.Popen在功能上都是对控制台进行读写操作的,其中的区别可参见我的另一篇文章:https://blog.youkuaiyun.com/Ls4034/article/details/89386857