Skip to main content
 首页 » 编程设计

python之从 python 中的管道读取是不可能的

2023年11月22日77shihaiming

你好,我在 python 2.6 中有以下代码:

command = "tcpflow -c -i any port 5559" 
port_sniffer = subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=1, shell=True) 
while True: 
    line = port_sniffer.stdout.readline() 
    #do some stuff with line 

此代码的目的是嗅探在端口 5559 上通信的两个进程(A 和 B)之间的流量。

现在让我描述一下我遇到的不同场景:

1) 上面的代码没有运行: A 和 B 正在通信,我可以使用日志和 linux 命令 netstat -napl | 清楚地看到它grep 5559 显示进程正在所需端口上进行通信。

2) 上面的代码没有运行,我通过直接从 shell 运行 tcpflow -c -i any port 5559 来嗅探: 我可以清楚地看到控制台上的通信:-)。

3) 上面的代码正在运行:进程无法通信。 netstat -napl | grep 5559 什么都不打印,日志给出错误!!!

4) 上面的代码在 Debug模式下运行:我似乎无法在 line = port_sniffer.stdout.readline()

行之后执行

我尝试使用迭代器而不是 while 循环(这并不重要,但我仍然指出了这一点)。我还尝试了不同的 bufsize 值(无、1 和 8)。

请帮忙!!

请您参考如下方法:

所以在快速阅读 the docs 之后我找到了这两句话:

On Unix, if args is a string, the string is interpreted as the name or path of the program to execute

The shell argument (which defaults to False) specifies whether to use the shell as the program to execute. If shell is True, it is recommended to pass args as a string rather than as a sequence.

基于此,我建议将您的命令重新创建为列表:

command = ["tcpflow -c", "-i any port 5559"]   #I don't know linux, so double check this line!! 

总体思路是这样的(也来自文档):

If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself. That is to say, Popen does the equivalent of:

Popen(['/bin/sh', '-c', args[0], args[1], ...]) 

此外,似乎要从您的进程中读取数据,您应该使用communicate()。所以

while True: 
    line = port_sniffer.stdout.readline() 

会变成

while True: 
    line = port_sniffer.communicate()[0] 

但请记住文档中的这条注释:

Note The data read is buffered in memory, so do not use this method if the data size is large or unlimited.