簡體   English   中英

Python filter()和sort()耗時太長

[英]Python filter() and sort() taking too long

我對Python很新,並將其用於打開文件夾的腳本,僅過濾文件,然后根據修改的時間按降序對它們進行排序。 在此之后,腳本從第一個日志文件開始,並搜索包含單詞“failure”的任何行,同時保留每次查找的行數。 然后它將此信息寫入單獨的文件。

我遇到的問題是這個腳本需要20-30分鍾才能運行。 該文件夾包含5k +文件,但不必遍歷所有文件。 該腳本將上次運行時觸及的第一個文件存儲在單獨的文件中,並在再次訪問該文件時停止處理。

我發現腳本耗時太長的地方是使用內置的filter()sort()方法。 任何人都可以提供原因,為什么它如此緩慢,並可能提供解決方案?

os.chdir(path)
files = filter(os.path.isfile, os.listdir(prod_path))
files.sort(key = os.path.getmtime, reverse = True)

for file in files:
    if file == break_file:
            break
    f = open(path + file).readlines()
    count = 0 #set count of errors to 0
    dest.write('Upload: ' + file[:file.index(".")] + '\n') #filename, need to truncate off filetype
    for line in f: #for each line in the the list of lines read from file
        if line.find('Failure') != -1 and line != f[0]:
            dest.write(line + '\n')
            count += 1
    dest.write('Number of Errors: ' + str(count) + '\n\n')

if dest.tell() == 0:
    dest.write('No files to process!')
dest.close()
update_file = open(last_run_file, 'w') #last_run_file stores break_file
update_file.write(str(files[0]))
print "done"    

問題,我注意到了:

  1. 正如@ dm03514提到的readlines()是一個壞主意。 這可能會導致高速交換。 最好for line in open(path + file):調用for line in open(path + file):
  2. if 'Failure' in line:改變條件if 'Failure' in line: 它會更加str.find() ,沒有調用str.find()可以更快
  3. line != f[0]是我想的第一行的檢查,所以最好跳過一次:

     log_file = open(path + file) # read first line log_file.readline() # read rest lines for line in log_file: if 'Failure' in line: 
  4. 多線程:Python有GIL,但它只影響CPU操作,因此您可以在單獨的線程中解析每個文件。 請參閱線程文檔

一些小的加速(你的帖子中沒有太多的細節,所以這是我能做的最好的):

import itertools

os.chdir(path)
fnames = [fname for fname in os.listdir(prod_path) if os.path.isfile(fname)
fnames.sort(key=os.path.getmtime, reverse=True)
firstfile, fnames = itertools.tee(itertools.takewhile(lambda fname: fname != break_file, fnames))
firstfile = next(firstfile)

with open('path/to/dest', 'w') as dest:
    errord = False
    for fname in fnames:
        with open(os.path.join(path, fname)) as infile:
            numErrors = 0
            dest.write('Upload: %s\n' %(fname.rsplit('.')[0]))
            infile.readline()
            for line in infile:
                if "Failure" not in line: continue
                dest.write(line)
                numErrors += 1
            dest.write('Number of Errors: %d\n\n' %numErrors)

    if not errord:
        dest.write('No files to process!')

with open(last_run_file, 'w') as update_file:
    update_file.write(firstfile)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM