Найти - Пользователи
Полная версия: Вычислить суммарный объем траффика на каждый хост
Начало » Python для новичков » Вычислить суммарный объем траффика на каждый хост
1
Imarden
Добрый день!

Читаю Основы Python — кратко. Часть 4. Генераторы списков

Рассмотрим простой пример. Допустим, у нас имеется лог-файл, в котором хранится статистика запросов к серверу в виде «ip bytes» через пробел, по одному хосту на
строку. Примерно так:

127.0.0.1 120
10.1.1.1 210
127.0.0.1 80
10.1.1.1 215
10.1.1.1 200
10.1.1.2 210

Нам необходимо вычислить суммарный объем траффика на каждый хост и выдать его в виде списка в поряке убывания траффика.
Программу для решения данной проблемы будет весьма недлинной Ее можно еще сильнее сократить, но это явно пойдет в ущерб ее читабельности.

#!/usr/bin/env python
#coding: utf8
# 1 считываем из файла строки и делим их на пары IP-адрес
raw = [x.split(" ")  for x in open("log.txt")]
# 2 заполняем словарь
rmp = {}
for ip, traffic in raw:
        if ip in rmp:
                rmp[ip] += int(traffic)
        else:
                rmp[ip] = int(traffic)
# 3 переводим в список и сортируем
lst = rmp.items()
lst.sort(key = lambda (key, val): key)
# 4 получаем результат
print "\n".join(["%s\t%d" % (host, traff) for host, traff in lst])

Но этот код для старого питона, и в Python 3 он выдает ошибки.

Я его немного поправил, но все равно не могу завести.

# -*- coding: utf-8 -*-
rmp = {}
with open('C:\\Python34\\irl.txt') as fp:
    print(fp)
    for line in fp:
        print(line, 'line')
        line1 = line.split()
        print(line1,'line1')
        for ip, traffic in line:
            print(ip, traffic)
            # print(ip, traffic, '=if')
            if ip in rmp:
                rmp[ip] +=int(traffic)
            else:
                pass
                print(ip, traffic, '=else')
                rmp[ip] +=int(traffic)
        lst = rmp.items()
        lst.sort(key = lambda key, val: key)
        #print("\n".join(["%s\t%d" % (host, traff) for host, traff in lst]))

<_io.TextIOWrapper name='C:\\Python34\\irl.txt' mode='r' encoding='cp1251'>
Traceback (most recent call last):
  File "C:\Python34\test.py", line 9, in <module>
127.0.0.1 120
 line
['127.0.0.1', '120'] line1
    for ip, traffic in line:
ValueError: need more than 1 value to unpack
[Finished in 0.1s]

Собственно вопрос, почему “ValueError: need more than 1 value to unpack”, когда - имеет два элемента ?

Если практически не изменять скрипт, то вот такой код, но там другая ошибка:

# -*- coding: utf-8 -*-
#!/usr/bin/env python
#coding: utf8
# 1 считываем из файла строки и делим их на пары IP-адрес
raw = [x.split(" ")  for x in open("C:\\Python34\\irl.txt")]
# 2 заполняем словарь
rmp = {}
for ip, traffic in raw:
        if ip in rmp:
                rmp[ip] += int(traffic)
        else:
                rmp[ip] = int(traffic)
# 3 переводим в список и сортируем
lst = rmp.items()
lst.sort(key = lambda key, val: key)
# 4 получаем результат
print("\n".join(["%s\t%d" % (host, traff) for host, traff in lst]))

Traceback (most recent call last):
  File "C:\Python34\test.py", line 15, in <module>
    lst.sort(key = lambda key, val: key)
AttributeError: 'dict_items' object has no attribute 'sort'
FishHook
lst = list(rmp.items())
Imarden
Спасибо. Исправил
lst.sort(key = lambda key, val: key)
на
lst.sort(key = lambda key: key)

# -*- coding: utf-8 -*-
#!/usr/bin/env python
#coding: utf8
# 1 считываем из файла строки и делим их на пары IP-адрес
raw = [x.split(" ")  for x in open("C:\\Python34\\irl.txt")]
print(raw)
# 2 заполняем словарь
rmp = {}
for ip, traffic in raw:
        if ip in rmp:
                rmp[ip] += int(traffic)
        else:
                rmp[ip] = int(traffic)
# 3 переводим в список и сортируем
lst = list(rmp.items())
print(lst)
lst.sort(key = lambda key: key)
# 4 получаем результат
print("\n".join(["%s\t%d" % (host, traff) for host, traff in lst]))

Но странные вещи происходят:
10.1.1.2 210
10.1.1.2 210
10.1.1.2 210
10.1.1.2 210
10.1.1.2 210
10.1.1.2 210

Вывод:
[['10.1.1.2', '210\n'], ['10.1.1.2', '210\n'], ['10.1.1.2', '210\n'], ['10.1.1.2', '210\n'], ['10.1.1.2', '210\n'], ['10.1.1.2', '210']]
[('10.1.1.2', 210), ('10.1.1.2', 1050)]
10.1.1.2	1050
10.1.1.2	210

Почему то первая строка обрабатывается по другому.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB