Найти - Пользователи
Полная версия: Медленный парсинг файла
Начало » Python для новичков » Медленный парсинг файла
1 2
aborodin
Всем привет.
Есть текстовый файл, в каждой строка
число;строка;ip-адрес;число
Всего 9600 строк. Я выбираю только ip-адреса следующим образом
    for text in file.readlines():
        text = text.rstrip()
        regex = re.findall(';[0-2]?[0-9][0-9]?.[0-2]?[0-9][0-9]?.[0-2]?[0-9][0-9]?.[0-2]?[0-9][0-9]?;', text)
        if regex is not None and regex not in ips:
            ips.append(regex)
Этот кусок выполняется 7 секунд, мне кажется это медленно. Посоветуйте что сделать чтобы ускорить выполнение скрипта. Спасибо.
bismigalis
вынеси из цикла создание регулярки
aborodin
сделал так
    regex_ = re.compile(';[0-2]?[0-9][0-9]?.[0-2]?[0-9][0-9]?.[0-2]?[0-9][0-9]?.[0-2]?[0-9][0-9]?;')
    for text in file.readlines():
        text = text.rstrip()
        regex = re.findall(regex_, text)
        if regex is not None and regex not in ips:
            ips.append(regex)
    print(time.time()-ts)
все равно 7.279864072799683 сек
FishHook
if regex is not None and regex not in ips:
Одна проверка явно лишняя
if not regex in ips:

И еще, in это дорогая операция, если ips список и если он большой. Если нельзя обойтись без этой проверки, то сделайте ips множеством.

l = range(10000)
s = set(range(10000))
def list_test():
	return 5088 in l
def set_test():
	return 5088 in s
if __name__ == '__main__':
	import timeit
	print(timeit.timeit("list_test()", setup="from __main__ import l, list_test", number=1000))
	print(timeit.timeit("set_test()", setup="from __main__ import s, set_test", number=1000 ))
результаты
0.0621750354767
0.000143051147461
Lexander
Зачем regex, если известен разделитель полей?
tuple(text.rstrip().split(";"))
даст тот же результат, но быстрее.

В остальном я бы мыслил так:

1. Какая версия Питона (есть разница между readlines, for line in f:)?
2. Сколько занимает чистый readlines (нужно локализовать место тормозов)?
3. Какой размер файла? Может его проще весь в память загнать с помощью f.read() ?
bismigalis
вызывай метод на созданном объекте регулярки
aborodin
FishHook, я попробую как осмыслю чем это может обернуться.

Lexander, есть не нулевая вероятность что может появиться “лишний” разделитель в текстовом поле
1. python 3.2
3. 832350 байт
masterito
Небольшая оптимизация использования памяти:
file.readlines() - читает все строки в list.

For reading lines from a file, you can loop over the file object. This is memory efficient, fast, and leads to simple code:
>>> for line in f:
        print line,
sergeek
re.findall возвращает список, эти вычисления:
regex not in ips:
            ips.append(regex)
будут на порядок тяжелей. Используй re.search с, как уже заметили, множеством.

text = text.rstrip()
наверное, не нужно
еще regex я бы все-таки назвал по-другому
fttk
Раз айпишники все равно уникальные, можно хранить в словаре, там гораздо быстрее лукапы делаются. Плюс непонятно зачем регулярка. Допустим вы не можете сделать сплит, потому что во второй колонке могут встречаться точки с запятой, тогда можно сделать индекс с конца.

Как-то так:
ips = {}
for line in f.readlines():
    ips[line.split(';')[-2]] = None
ips = ips.keys()
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