Цитирование через большие файлы занимает несколько часов в Python

Это мой второй день работы в Python. Я работал над этим на C ++ некоторое время, но решил попробовать Python. Моя программа работает так, как ожидалось. Однако, когда я обрабатываю один файл за один раз без цикла glob, он занимает около получаса за файл. Когда я включаю glob, цикл занимает около 12 часов для обработки 8 файлов.

Мой вопрос в том, есть ли в моей программе что-то, что замедляет ее? есть ли что-нибудь, что я должен делать, чтобы сделать это быстрее?

У меня есть папка с большими файлами. Например

file1.txt (6gb) file2.txt (5.5gb) file3.txt (6gb)

Если это помогает, каждая строка данных начинается с символа, который сообщает мне, как отформатированы остальные символы, поэтому у меня есть все инструкции if elif. Строка данных будет выглядеть так: T35201 M352 RZNGA AC

Я пытаюсь прочитать каждый файл, выполнить синтаксический анализ с использованием разделов, а затем сохранить файл.

Компьютер имеет 32 ГБ оперативной памяти, поэтому мой метод состоит в том, чтобы читать каждый файл в ram, а затем прокручивать файл, а затем сохранять, очищая баран для следующего файла.

Я включил файл, чтобы вы могли видеть методы, которые я использую. Я использую оператор if elif, который использует около 10 различных команд elif. Я пробовал словарь, но я не мог понять это, чтобы спасти свою жизнь.

Любые ответы были бы полезными.

import csv import glob for filename in glob.glob("/media/3tb/5may/*.txt"): f = open(filename,'r') c = csv.writer(open(filename + '.csv','wb')) second=0 mill=0 for line in f.readlines(): #print line event=0 ticker=0 marketCategory=0 variable = line[0:1] if variable is 'T': second = line[1:6] mill=0 else: second = second if variable is 'R': ticker = line[1:7] marketCategory = line[7:8] elif variable is ... elif variable is ... elif ... elif ... elif ... elif ... elif if variable (!= 'T') and (!= 'M') c.writerow([second,mill,event ....]) f.close() 

ОБНОВЛЕНИЕ Каждое из утверждений elif почти идентично. Единственными частями, которые меняются, являются способы разделить линии. Вот два утверждения elif (Всего 13, и они почти все идентичны, за исключением того, что они разделены).

  elif variable is 'C': order = line[1:10] Shares = line[10:16] match = line[16:25] printable = line[25:26] price = line[26:36] elif variable is 'P': ticker = line[17:23] order = line[1:10] buy = line[10:11] shares = line[11:17] price = line[23:33] match = line[33:42] 

UPDATE2 Я запустил код, используя for file in f два раза два раза. В первый раз я запустил один файл без for filename in glob.glob("/media/3tb/file.txt"): и потребовалось около 30 минут, вручную for filename in glob.glob("/media/3tb/file.txt"): путь к файлу для одного файла.

Я снова запустил его for filename in glob.glob("/media/3tb/*file.txt") и потребовался час только для одного файла в папке. Добавляет ли код glob столько времени?

4 Solutions collect form web for “Цитирование через большие файлы занимает несколько часов в Python”

Вот:

 for line in f.readlines(): 

Вы должны просто сделать это:

 for line in f: 

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

Всякий раз, когда вы спрашиваете: «какая часть этого замедляет все это?» ответ «профиль». Существует отличное описание того, как это сделать в документации Python на Python Profiler . Кроме того, как указывает Джон Звинк, вы загружаете слишком много в память сразу и должны загружать только одну строку за раз (объекты файлов «итерируются» в Python).

Лично я предпочитаю, что Perl называет «таблицу рассылки» огромным if..elif...elif monstrosity. Эта веб-страница описывает питоновский способ сделать это. Это словарь ключей к функциям, который не работает во всех случаях, но для простого, if x==2:...elif x==3... (т.е. включение значения одной переменной), он отлично работает ,

Используйте iterable (используя выход), чтобы «буферизировать» больше строк в памяти, чем только одну строку за раз, но не весь файл за раз.

 def readManyLines(fObj,num=1000): lines = fObj.readlines(num) for line in lines: yield line f = open(filename,'r') for line in readManyLines(f): process(line) 

Не уверен, что это вообще помогает, но попробуйте использовать это вместо glob.glob, чтобы исключить, что это проблема. Я на окнах, поэтому я не могу быть на 100% уверенным, что это работает под Unix, но я не понимаю, почему это не так.

 import re import os import csv def find_text_files(root): """Find .txt files under a given directory""" foundFiles = [] for dirpath, dirnames, filenames in os.walk(root): for file in filenames: txt = re.compile(r'txt$',re.I,).search(file) if txt: foundFiles.append(os.path.join(dirpath,file)) return foundFiles txtfiles = find_text_files('d:\files') #replace the path with yours for filename in txtfiles: f = open(filename,'r') c = csv.writer(open(filename + '.csv','wb')) 
Interesting Posts
Python - лучший язык программирования в мире.