views:

536

answers:

3

The output of /proc/net/dev on Linux looks like this:

Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
    lo:18748525  129811    0    0    0     0          0         0 18748525  129811    0    0    0     0       0          0
  eth0:1699369069 226296437    0    0    0     0          0      3555 4118745424 194001149    0    0    0     0       0          0
  eth1:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
  sit0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0

How can I use Python to parse this output into key:value pairs for each interface? I have found this forum topic for achieving it using shell scripting and there is a Perl extension but I need to use Python.

+1  A: 

Does this help?

dev = open("/proc/net/dev", "r").readlines()
header_line = dev[1]
header_names = header_line[header_line.index("|")+1:].replace("|", " ").split()

values={}
for line in dev[2:]:
    intf = line[:line.index(":")].strip()
    values[intf] = [int(value) for value in line[line.index(":")+1:].split()]

    print intf,values[intf]

Output:

lo [803814, 16319, 0, 0, 0, 0, 0, 0, 803814, 16319, 0, 0, 0, 0, 0, 0]
eth0 [123605646, 102196, 0, 0, 0, 0, 0, 0, 9029534, 91901, 0, 0, 0, 0, 0, 0]
wmaster0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
eth1 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
vboxnet0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
pan0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

You could, of course, use the header names in header_names to construct a dict of dicts.

wr
+5  A: 

this is pretty formatted input and you can easily get columns and data list by splitting each line, and then create a dict of of it.

here is a simple script without regex

lines = open("/proc/net/dev", "r").readlines()

columnLine = lines[1]
_, receiveCols , transmitCols = columnLine.split("|")
receiveCols = map(lambda a:"recv_"+a, receiveCols.split())
transmitCols = map(lambda a:"trans_"+a, transmitCols.split())

cols = receiveCols+transmitCols

faces = {}
for line in lines[2:]:
    if line.find(":") < 0: continue
    face, data = line.split(":")
    faceData = dict(zip(cols, data.split()))
    faces[face] = faceData

import pprint
pprint.pprint(faces)

it outputs

{'    lo': {'recv_bytes': '7056295',
            'recv_compressed': '0',
            'recv_drop': '0',
            'recv_errs': '0',
            'recv_fifo': '0',
            'recv_frame': '0',
            'recv_multicast': '0',
            'recv_packets': '12148',
            'trans_bytes': '7056295',
            'trans_carrier': '0',
            'trans_colls': '0',
            'trans_compressed': '0',
            'trans_drop': '0',
            'trans_errs': '0',
            'trans_fifo': '0',
            'trans_packets': '12148'},
 '  eth0': {'recv_bytes': '34084530',
            'recv_compressed': '0',
            'recv_drop': '0',
            'recv_errs': '0',
            'recv_fifo': '0',
            'recv_frame': '0',
            'recv_multicast': '0',
            'recv_packets': '30599',
            'trans_bytes': '6170441',
            'trans_carrier': '0',
            'trans_colls': '0',
            'trans_compressed': '0',
            'trans_drop': '0',
            'trans_errs': '0',
            'trans_fifo': '0',
            'trans_packets': '32377'}}
Anurag Uniyal
you can further improved it by striping interface names and convert values to float or int
Anurag Uniyal
For a second I thought that _ would work as in Haskell, but sadly it doesn't :(
Armandas
_ just is a placeholder variable name, how does it work in haskell?
Anurag Uniyal
It matches everything, so you can use it to get a tail of a list for example. The same functionality is implemented in Python3: http://www.python.org/dev/peps/pep-3132/
Armandas
A: 
#!/usr/bin/env python
from __future__ import with_statement
import re
import pprint


ifaces = {}


with open('/proc/net/dev') as fd:
    lines = map(lambda x: x.strip(), fd.readlines())


lines = lines[1:]


lines[0] = lines[0].replace('|', ':', 1)
lines[0] = lines[0].replace('|', ' ', 1)
lines[0] = lines[0].split(':')[1]


keys = re.split('\s+', lines[0])
keys = map(lambda x: 'rx' + x[1] if x[0] < 8 else 'tx' + x[1], enumerate(keys))


for line in lines[1:]:
    interface, values = line.split(':')
    values = re.split('\s+', values)

    if values[0] == '':
        values = values[1:]

    values = map(int, values)

    ifaces[interface] = dict(zip(keys, values))


pprint.pprint(ifaces)
null