无限期 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())
任务是:尝试使用 "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())