Python Popen的stdout输出到stderr中
我需要用Python的subprocess
模块来获取tshark -D
的输出。下面是tshark -D
的输出内容:
$ tshark -D
1. eth0
2. any (伪设备,可以在所有接口上捕获)
3. lo
然后用Python运行时,它会给出:
>>> import subprocess
>>> p = subprocess.Popen(["tshark", "-D"], stdout=subprocess.PIPE) ###1
>>> 1. eth0
2. any (Pseudo-device that captures on all interfaces)
3. lo
>>> p = subprocess.Popen(["tshark", "-D"], stderr=subprocess.PIPE,stdout=subprocess.PIPE) ###2
>>> p.stderr.read()
'1. eth0\n2. any (Pseudo-device that captures on all interfaces)\n3. lo\n'
>>> p.stdout.read()
''
在第#1行,输入命令后会显示输出。而在第#2行,所需的输出出现在stderr
中。为什么会这样呢?
3 个回答
tshark -D
这个命令总是把信息输出到错误信息流(stderr)里。在第一种情况中,因为你没有捕捉到错误信息流,所以它直接显示在你的控制台上。
在第二种情况下,因为你同时捕捉了标准输出(stdout)和错误信息流(stderr),所以标准输出是空的(''),而错误信息流则包含了输出内容。
对于第一个问题:
因为你没有处理标准输出和错误输出,所以命令的打印结果会直接显示在屏幕上。如果你想处理标准输出,你需要同时处理标准输出和错误输出。否则,你实际上无法捕捉到标准输出。当你指定标准输出时,也应该同时处理标准错误的打印。
可以想象成下面这样,如果你有一个名为“func_my.py”的模块,里面有一个函数:
def func_my():
print "Hello"
return "World"
if __name__ == "__main__":
func_my()
当你调用这个函数时,如果不处理控制台的输出,字符串“hello”就会直接显示在控制台上。
p = subprocess.Popen(["python", "func_my.py"], stdout=subprocess.PIPE)
这将始终打印出“hello”。
对于第二个问题:你确实捕捉到了标准输出和错误输出,但你犯了一个错误。你把所有的输出都放到了标准输出和错误输出中。正确的方法应该是下面这样:
p = subprocess.Popen(["tshark", "-D"], stderr=subprocess.STDOUT,stdout=subprocess.PIPE)
p.stderr.read()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'read'
p.stdout.read()
"WARNING: gnome-keyring:: couldn't connect to: /tmp/keyring-UBTaGc/pkcs11: No such file or directory\ntshark: There are no interfaces on which a capture can be done\n"
希望这能帮到你!
如果你想要获取所有输出,不管是子进程在标准输出(stdout)还是错误输出(stderr)上打印的内容,你可以使用 stderr=STDOUT
和 subprocess.check_output
这两个选项。
from subprocess import check_output, STDOUT
all_output = check_output(['tshark', '-D'], stderr=STDOUT)
tshark
的手册上写着:
-D 打印出 TShark 可以捕获的接口列表,并退出。
手册没有说明输出一定要在错误输出上。不过在我的系统上,它确实只把诊断信息打印到错误输出上。标准输出可能是留给捕获的数据打印的。