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.
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
.
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())
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)
...