Уведомления

Группа в Telegram: @pythonsu

#1 Сен. 4, 2015 06:37:47

Imarden
Зарегистрирован: 2015-02-20
Сообщения: 44
Репутация: +  0  -
Профиль   Отправить e-mail  

Вычислить суммарный объем траффика на каждый хост

Добрый день!

Читаю Основы 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'

Отредактировано Imarden (Сен. 4, 2015 06:41:02)

Офлайн

#2 Сен. 4, 2015 07:08:46

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Вычислить суммарный объем траффика на каждый хост

lst = list(rmp.items())



Офлайн

#3 Сен. 4, 2015 07:39:35

Imarden
Зарегистрирован: 2015-02-20
Сообщения: 44
Репутация: +  0  -
Профиль   Отправить e-mail  

Вычислить суммарный объем траффика на каждый хост

Спасибо. Исправил

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

Почему то первая строка обрабатывается по другому.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version