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

荒凉一梦 提交于 2019-12-17 21:17:34

问题


The task is: Try to send ping in python using the most basic form like "ping 8.8.8.8". After some time terminate the ping command (In a terminal, one will do Ctrl+C) and get its output. The last several lines of output which shows the ping statistics are of particular interest.

Two methods tried, did not work. My OS version is Mac OS X 10.10.1.

First method uses module pexpect, and ping will stop after about 17 seconds though I did not ask it to stop:

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

Second Method uses module subprocess, and the last several lines of ping output are lost:

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

I'd appreciate any help! "ping -c XXX" is not accepted.


回答1:


The second solution you have is great. There's just one issue with obtaining your desired behavior (getting the ping's "conclusion"): You're sending the wrong signal to the process.

When you terminate the process from a shell, you traditionally send a SIGINT signal. See "bash - How does Ctrl-C terminate a child process?". This allows the process to "wrap up" (e.g., cleaning up temprorary files, providing debug information).

import signal

# Open process

child.send_signal(signal.SIGINT)

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

# Echo output

Popen.terminate, which you're using now, sends a SIGTERM instead of a SIGINT.




回答2:


ping will block in your code as soon as it fills its stdout OS pipe buffer (~65K on my system). You need to read the output:

#!/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())



回答3:


Popen.terminate() sends SIGTERM on Posix OSs. However, by default CTRL+C sends SIGINT. So to get similar behavior like pressing CTRL+C, you can do something like this:

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


来源:https://stackoverflow.com/questions/27994854/ping-for-indefinite-amount-of-time-and-get-its-output-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!