To write subprocess' output to a file, pass the file object as stdout:
import subprocess
with open(ip + '--ping.log', 'wb', 0) as file:
subprocess.call(['ping', ..., ip], stdout=file)
In your case, you probably don't want to write the stdout as is. To do ICMP ping, if you can't run your script as an administrator then you have to use an external setuid command such as ping
. ping
command options and output may vary between different systems. On my platform, a regex suggested in this discussion works:
#!/usr/bin/env python
import re
import sys
from subprocess import Popen, PIPE
avg_pattern = br"rtt min/avg/max/mdev = \d+.\d+/(\d+.\d+)/\d+.\d+/\d+.\d+"
for ip in sys.argv[1:]:
p = Popen(['ping', '-c', '5', ip], stdout=PIPE)
output = p.communicate()[0]
avg_ms = float(re.search(avg_pattern, output).group(1))
print("{ip},{avg_ms}".format(**vars()))
Example:
$ python -m avg_ping google.com facebook.com > avg-ping-time.csv
The command runs avg_ping.py
and writes its output to avg-ping-time.csv
file.
Unrelated: you could make the ping requests in parallel:
#!/usr/bin/env python
import re
import sys
import subprocess
from multiprocessing.pool import ThreadPool
def ping(ip, pattern=br"rtt min/avg/max/mdev = \d+.\d+/(\d+.\d+)/\d+.\d+/\d+.\d+"):
p = subprocess.Popen(['ping', '-c', '5', ip], stdout=subprocess.PIPE)
return ip, float(re.search(pattern, p.communicate()[0]).group(1))
pool = ThreadPool(20) # no more than 20 concurrent pings
for ip, avg_ms in pool.imap_unordered(ping, sys.argv[1:]):
print("{ip},{avg_ms}".format(**vars()))
The usage is exactly the same.