2016-04-05 4 views
1

Я пытаюсь открыть определенные строки из нескольких файлов и вернуть строки каждого файла. Мое решение занимает много времени. есть ли у вас предложения?
func.filename: имя данного файла
func.start_line: отправной точкой в ​​данном файле
func.endline: конечную точку в данном файлеоткрытие определенных строк внутри нескольких файлов

def method_open(func): 
    try: 
     body = open(func.filename).readlines()[func.start_line: 
               func.end_line] 
    except IOError: 
     body = [] 
     stderr.write("\nCouldn't open the referenced method inside {0}". 
        format(func.filename)) 
     stderr.flush() 
    return body 

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

+0

Почему это занимает так много времени? Является ли файл очень большим? Если да, то насколько велика? –

+0

Вы можете попробовать [linecache] (https://docs.python.org/2/library/linecache.html) модуль или 'itertools.islice' и посмотреть, не слишком ли они занимают много времени. Подробнее см. Здесь: http://stackoverflow.com/questions/2081836/reading-specific-lines-only-python –

+0

Нет, я думаю, проблема в том, что я открываю и закрываю файл снова и снова, abut linecache может быть интересным, если бы он имел возможность объединять строки в одно и то же время. –

ответ

2

Проблема с readlines заключается в том, что он считывает весь файл в память, а linecache делает то же самое.

Вы можете сэкономить время, читая одну строку за один раз и разорвать цикл, как только вы достигнете func.endline

Но лучший способ я нашел, чтобы использовать itertools.islice

Здесь результаты некоторые тесты, которые я сделал на 130MB файле ~ 9701k линий:

--- 1.43700003624 seconds --- f_readlines 
--- 1.00099992752 seconds --- f_enumerate 
--- 1.1400001049 seconds --- f_linecache 
--- 0.0 seconds --- f_itertools_islice 

Здесь вы можете найти сценарий, я использовал

import time 
import linecache 
import itertools 


def f_readlines(filename, start_line, endline): 
    with open(filename) as f: 
     f.readlines()[5000:10000] 


def f_enumerate(filename, start_line, endline): 
    result = [] 
    with open(filename) as f: 
     for i, line in enumerate(f): 
      if i in range(start_line, endline): 
       result.append(line) 
      if i > endline: 
       break 


def f_linecache(filename, start_line, endline): 
    result = [] 
    for n in range(start_line, endline): 
     result.append(linecache.getline(filename, n)) 


def f_itertools_islice(filename, start_line, endline): 
    result = [] 
    with open(filename) as f: 
     resultt = itertools.islice(f, start_line, endline) 
     for i in resultt: 
      result.append(i) 


def runtest(func_to_test): 
    filename = "testlongfile.txt" 
    start_line = 5000 
    endline = 10000 
    start_time = time.time() 
    func_to_test(filename, start_line, endline) 
    print("--- %s seconds --- %s" % ((time.time() - start_time),func_to_test.__name__)) 

runtest(f_readlines) 
runtest(f_enumerate) 
runtest(f_linecache) 
runtest(f_itertools_islice) 
+0

интересно! Это фактически отвечает на мой вопрос о том, какой метод является самым быстрым, в отличие от упомянутого вопроса: http://stackoverflow.com/questions/2081836/reading-specific-lines-only-python Спасибо! –

Смежные вопросы