Python Popen的stdout输出到stderr中

0 投票
3 回答
1086 浏览
提问于 2025-04-18 00:16

我需要用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 个回答

0

tshark -D 这个命令总是把信息输出到错误信息流(stderr)里。在第一种情况中,因为你没有捕捉到错误信息流,所以它直接显示在你的控制台上。

在第二种情况下,因为你同时捕捉了标准输出(stdout)和错误信息流(stderr),所以标准输出是空的(''),而错误信息流则包含了输出内容。

0

对于第一个问题:
因为你没有处理标准输出和错误输出,所以命令的打印结果会直接显示在屏幕上。如果你想处理标准输出,你需要同时处理标准输出和错误输出。否则,你实际上无法捕捉到标准输出。当你指定标准输出时,也应该同时处理标准错误的打印。

可以想象成下面这样,如果你有一个名为“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"

希望这能帮到你!

2

如果你想要获取所有输出,不管是子进程在标准输出(stdout)还是错误输出(stderr)上打印的内容,你可以使用 stderr=STDOUTsubprocess.check_output 这两个选项。

from subprocess import check_output, STDOUT

all_output = check_output(['tshark', '-D'], stderr=STDOUT)

tshark 的手册上写着:

-D 打印出 TShark 可以捕获的接口列表,并退出。

手册没有说明输出一定要在错误输出上。不过在我的系统上,它确实只把诊断信息打印到错误输出上。标准输出可能是留给捕获的数据打印的。

撰写回答