我对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) + 'nn')
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"
我注意到的问题:
- 正如@dm03514提到的
readlines()
这是一个坏主意。这可能会导致高交换。最好打电话给for line in open(path + file):
- 将条件更改为
if 'Failure' in line:
。它会更pythonic,没有调用str.find()
可以更快 -
我想
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:
-
多线程: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: %sn' %(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: %dnn' %numErrors)
if not errord:
dest.write('No files to process!')
with open(last_run_file, 'w') as update_file:
update_file.write(firstfile)