Вопрос по parsing, linux, python – Как я могу разобрать вывод / proc / net / dev в пары ключ: значение для интерфейса, используя Python?

2

Выход из/ Proc / нетто / DEV на линуксе выглядит так:

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

Как я могу использовать Python для разбора этого вывода в пары ключ: значение для каждого интерфейса? я нашелэта тема форума для достижения этого с помощью сценариев оболочки и естьрасширение Perl но мне нужно использовать Python.

Ваш Ответ

3   ответа
1
#!/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)
Спасибо за версию Python.
1

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]

Выход:

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]

Конечно, вы можете использовать имена заголовков вheader_names построить диктат диктата.

10

и вы можете легко получить столбцы и список данных, разделив каждую строку, а затем создать ее из нее.

вот простой скрипт без регулярных выражений

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)

это выводит

{'    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'}}
На секунду я подумал, что _ будет работать как в Haskell, но, к сожалению, это не так :(
_ просто имя переменной-заполнителя, как она работает в haskell?
Зачемif line.find(":") < 0: continue ?
Вы можете улучшить его, раздвигая имена интерфейсов и конвертируя значения в float или int
Это соответствует всему, так что вы можете использовать его, например, для получения списка. Та же функциональность реализована в Python3:python.org/dev/peps/pep-3132

Похожие вопросы