Ping for an indefinite amount of time and get its output in Python

Task: Try submitting ping to python using the most basic form, such as "ping 8.8.8.8". After some time, complete the ping command (in the terminal, one will do Ctrl + C) and get its output. Of particular interest are the last few lines of output, which show ping statistics.

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

The first method uses the pexpect module, and ping will stop after about 17 seconds, although 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 

The second method uses the module subprocess, and the last few 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 would be grateful for any help! "ping -c XXX" is not accepted.

+1
python subprocess pexpect ping
Jan 17 '15 at 0:28
source share
3 answers

Your second solution is great. There is only one problem with getting the desired behavior (getting ping output): you send the wrong signal to the process.

When you complete the process from the shell, you traditionally send a SIGINT signal. See bash - How does Ctrl-C terminate a child process? . This allows the process to "wrap up" (for example, clear temporary files by providing debugging 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 that you are using now sends SIGTERM instead of SIGINT .

0
Jan 17 '15 at 0:53
source share

ping will be blocked in your code as soon as it fills its buffer buffer of the operating system stdout (~ 65K on my system). You need to read the result:

 #!/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()) 
+1
Jan 17 '15 at 1:17
source share

Popen.terminate () sends SIGTERM to the Posix OS. However, by default, CTRL + C sends a SIGINT. To get a similar behavior, for example by pressing CTRL + C, you can do something like this:

 ... import signal ... time.sleep(5) child.send_signal(signal.SIGINT) ... 
0
Jan 17
source share



All Articles