0

I need to create a csv file with the output from the ping cmd so i can generate a graph. but how can i make the avg. responstime from the ping be written ro a csv file ? (Excel)

import subprocess

list_of_ips = ["facebook.com", "google.com"]
for ip in list_of_ips:
    ping_process = subprocess.Popen(['ping', '-c', '5', ip], stdout=subprocess.PIPE)
stdout = ping_process.stdout.read()
jfs
  • 399,953
  • 195
  • 994
  • 1,670

2 Answers2

0

You could try to handle the response you got in stdout with regex and get your average time. Or you could use a python module and do it by youself like it's described in this thread Ping a site in Python?

Edit: The simplest way would be with regex. I have modified your code snipet a bit :

import subprocess, re

list_of_ips = ["facebook.com", "google.com"]
for ip in list_of_ips:
    ping_process = subprocess.Popen(['ping', '-c', '5', ip], stdout=subprocess.PIPE)
    stdout = ping_process.stdout.read()
    match = re.search(r'\d*\.\d*\/(\d*\.\d*)\/\d*\.\d*\/\d*\.\d*', stdout)
    avg = match.group(1)
    print('{}: {}ms'.format(ip, avg))

Edit2: OK now it should fit ;)

import subprocess, re, csv

list_of_ips = ["facebook.com", "google.com"]
avgTimeList = []
for ip in list_of_ips:
    ping_process = subprocess.Popen(['ping', '-c', '5', ip], stdout=subprocess.PIPE)
    stdout = ping_process.stdout.read()
    match = re.search(r'\d*\.\d*\/(\d*\.\d*)\/\d*\.\d*\/\d*\.\d*', stdout)
    avg = match.group(1)
    avgTimeList.append([ip, avg])

with open('avgTimes.csv', 'w') as csvfile:
    csvWriter = csv.writer(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL)
    for data in avgTimeList:
        csvWriter.writerow(data)
Community
  • 1
  • 1
Ben
  • 673
  • 3
  • 11
  • Aha :D I actually all ready had written the regex, but my biggest problem is to write it to a file instead of printing it. – Daniel Guldberg Aaes Nov 23 '15 at 12:54
  • @DanielGuldbergAaes: beware, there could be newline issues. Use `'wb'` mode with `csv` module on Python 2. – jfs Nov 23 '15 at 14:48
0

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.

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670