(Python) Counting lines in a huge (>10GB) file as fast as possible
我现在有一个非常简单的脚本,它使用
1 2 3 4 5 6 | i = 0 f = open("C:/Users/guest/Desktop/file.log","r") for i, line in enumerate(f): pass print i + 1 f.close() |
这需要大约3.5分钟的时间来完成一个15GB的日志文件,其中包含大约3000万行。如果我能在两分钟或更短的时间内完成这项工作,那就太好了,因为这些是日常日志,我们希望每月进行一次分析,因此代码必须处理30个大约15GB的日志,可能超过一个半小时,我们希望将服务器上的时间和内存负载降到最低。
我也会解决一个好的近似/估计方法,但它需要大约4西格图准确…
谢谢您!
伊格纳西奥的回答是的先生也可能会失败,但如果你有一个32位的过程。 P / < >
但也许它可以useful读到的文件块明智的,然后在每一块的
1 2 3 4 5 6 7 8 9 | def blocks(files, size=65536): while True: b = files.read(size) if not b: break yield b with open("file","r") as f: print sum(bl.count(" ") for bl in blocks(f)) |
会做你的工作。 P / < >
注意,我不要打开的文件为二进制,这样的
将converted到
为Python 3,和使它更强大,为阅读的文件与所有kinds的字符数: P / < >
1 2 3 4 5 6 7 8 9 | def blocks(files, size=65536): while True: b = files.read(size) if not b: break yield b with open("file","r",encoding="utf-8",errors='ignore') as f: print (sum(bl.count(" ") for bl in blocks(f))) |
我知道它的不公平,但你能做到这一点 P / < >
1 | int(subprocess.check_output("wc -l C:\\alarm.bat").split()[0]) |
如果你是在Windows,看看coreutils。 P / < >
一个快速,1在线解决方案: P / < >
1 | sum(1 for i in open(file_path, 'rb')) |
它应该工作文件的arbitrary尺寸。 P / < >
mmap同步的文件,和计数的newlines起来。 P / < >
I’d extend GL的答案和跑他/她使用的代码multiprocessing Python模块为更快的count: P / < >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | def blocks(f, cut, size=64*1024): # 65536 start, chunk =cut iter=0 read_size=int(size) _break =False while not _break: if _break: break if f.tell()+size>start+chunk: read_size=int(start+chunk- f.tell() ) _break=True b = f.read(read_size) iter +=1 if not b: break yield b def get_chunk_line_count(data): fn, chunk_id, cut = data start, chunk =cut cnt =0 last_bl=None with open(fn,"r") as f: if 0: f.seek(start) bl = f.read(chunk) cnt= bl.count(' ') else: f.seek(start) for i, bl in enumerate(blocks(f,cut)): cnt += bl.count(' ') last_bl=bl if not last_bl.endswith(' '): cnt -=1 return cnt .... pool = multiprocessing.Pool(processes=pool_size, initializer=start_process, ) pool_outputs = pool.map(get_chunk_line_count, inputs) pool.close() # no more tasks pool.join() |
这将improve列入20 folds性能。 我wrapped它到脚本和把它放到github。 P / < >