无限期 ping 并在 Python 中获得其输出

ping for indefinite amount of time and get its output in Python

任务是:尝试使用 "ping 8.8.8.8" 等最基本的形式在 python 中发送 ping。一段时间后终止 ping 命令(在终端中,将执行 Ctrl+C)并获得其输出。显示 ping 统计信息的最后几行输出特别令人感兴趣。

两种方法都试过了,都不行。我的 OS 版本是 Mac OS X 10.10.1.

第一种方法使用 pexpect 模块,虽然我没有要求它停止,但 ping 会在大约 17 秒后停止:

import pexpect
import time
child = pexpect.spawn('ping 8.8.8.8')
(x, y) = child.getwinsize()
print x
print y
time.sleep(21)
child.terminate()
x = child.read()
print x

第二种方法使用module subprocess,ping输出最后几行丢失:

import time
from subprocess import PIPE, Popen
child = Popen(['ping', '8.8.8.8'], stdin = PIPE, stdout = PIPE, stderr = PIPE)
time.sleep(5)
child.terminate()
x = child.stdout.read()
print x
x = child.stderr.read()
print x

如有任何帮助,我将不胜感激! "ping -c XXX" 未被接受。

你的第二个解决方案很好。获得所需行为(获得 ping 的 "conclusion")只有一个问题:您向进程发送了错误的信号。

当您从 shell 终止进程时,您通常会发送一个 SIGINT 信号。参见 "bash - How does Ctrl-C terminate a child process?"。这允许进程 "wrap up"(例如,清理临时文件,提供调试信息)。

import signal

# Open process

child.send_signal(signal.SIGINT)

# Provide some time for the process to complete
time.sleep(1)

# Echo output
您现在使用的

Popen.terminate 发送 SIGTERM 而不是 SIGINT.

Popen.terminate() 在 Posix 操作系统上发送 SIGTERM。但是,默认情况下 CTRL+C 发送 SIGINT。因此,要获得类似按 CTRL+C 的行为,您可以这样做:

...
import signal
...
time.sleep(5)
child.send_signal(signal.SIGINT)
...

ping 将在您的代码填满其标准输出 OS 管道缓冲区(在我的系统上约为 65K)后立即阻塞。您需要阅读输出:

#!/usr/bin/env python
import signal
from subprocess import Popen, PIPE
from threading import Timer

child = Popen(['ping', '8.8.8.8'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
Timer(5, child.send_signal, [signal.SIGINT]).start() # Ctrl+C in 5 seconds
out, err = child.communicate() # get output
print(out.decode())
print('*'*60)
print(err.decode())