早些时候,我问过这个问题:
How can I perform a ping or traceroute using native python?
但是因为python没有以root身份运行,所以它无法打开在本机python中执行ping / traceroute所需的原始ICMP套接字。
这让我回到使用系统的ping / traceroute shell命令。这个问题有几个使用subprocess
模块的例子似乎运作良好:
我还有一个要求:我需要能够在生成时访问输出(例如,对于长时间运行的traceroute。)
上面的示例都运行shell命令,然后只有在命令完成后才能访问完整输出。有没有办法在生成命令输出时访问它?
编辑:根据Alex Martelli的回答,这是有效的:
import pexpect
child = pexpect.spawn('ping -c 5 www.google.com')
while 1:
line = child.readline()
if not line: break
print line,
答案 0 :(得分:6)
pexpect是我达到的目标,“默认情况下”,对于任何需求,例如你的 - 还有其他类似的模块,但是pexpect几乎总是最丰富,最稳定,最成熟的模块。如果我不得不在Windows下正确运行(ping和traceroute可能有他们自己的问题),那么我会费心寻找替代方案的一个案例 - 让我们知道你是否就是这种情况,我们会看看可以安排什么! - )
答案 1 :(得分:4)
您应该阅读subprocess模块的文档,它描述了如何运行外部进程并实时访问其输出。
基本上,你做
from subprocess import Popen, PIPE
p = Popen(['tracert', host], stdout=PIPE)
while True:
line = p.stdout.readline()
if not line:
break
# Do stuff with line
实际上,您链接的SO问题中的答案非常接近您的需求。 Corey Goldberg's answer使用了一个管道readline
,但由于它与-n 1
运行ping,因此它的持续时间不足以产生影响。
答案 2 :(得分:1)
您可以为子流程创建一个tty对,并在其中运行。根据C标准(C99 7.19.3),唯一的时间stdout是行缓冲的(与完全缓冲相反,这是你所说的你不想要的)是它的终端。 (或者孩子显然叫做setvbuf())。
查看os.openpty()。
未经测试的代码:
master, slave = os.openpty()
pid = os.fork()
if pid == 0:
os.close(master)
os.dup2(slave, 0)
os.dup2(slave, 1)
os.dup2(slave, 2)
os.execv("/usr/sbin/traceroute", ("traceroute","4.2.2.1"))
# FIXME: log error somewhere
os.exit(1)
os.close(slave)
while True:
d = os.read(master)
if len(d) == 0:
break
print d
os.waitpid(pid, 0)
请注意,让子进程(在fork()之后)调用setvbuf()将不工作,因为setvbuf()是一个libc函数而不是一个系统调用。它只是改变当前进程输出的状态,当加载新的二进制文件时,它将在exec调用时被覆盖。
答案 3 :(得分:1)
这是另一种方法:
# const_output.py
import sys
from subprocess import Popen
if len(sys.argv) < 2:
print 'Usage: const_output.py "command to watch"'
sys.exit(1)
cmd_line = sys.argv[1:]
p = Popen(cmd_line)
p.communicate()[0]
使用示例:
跟踪路由:
> python const_output.py traceroute 10.0.0.38
traceroute to 10.0.0.38 (10.0.0.38), 30 hops max, 60 byte packets
1 10.0.0.38 (10.0.0.38) 0.106 ms 0.023 ms 0.021 ms
平:
> python const_output.py ping 10.0.0.38
PING 10.0.0.38 (10.0.0.38) 56(84) bytes of data.
64 bytes from 10.0.0.38: icmp_seq=1 ttl=64 time=0.046 ms
64 bytes from 10.0.0.38: icmp_seq=2 ttl=64 time=0.075 ms
64 bytes from 10.0.0.38: icmp_seq=3 ttl=64 time=0.076 ms
64 bytes from 10.0.0.38: icmp_seq=4 ttl=64 time=0.073 ms
顶
> python const_output.py top
# you will see the top output