如何在Python中廉价地获得大文件的行数?

2024-03-29 15:55:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要得到python中一个大文件(数十万行)的行数。什么是记忆和时间最有效的方法?

现在我想:

def file_len(fname):
    with open(fname) as f:
        for i, l in enumerate(f):
            pass
    return i + 1

有可能做得更好吗?


Tags: 文件方法记忆inforlendefas
3条回答

一行,可能很快:

num_lines = sum(1 for line in open('myfile.txt'))

我相信内存映射文件将是最快的解决方案。我尝试了四个函数:OP发布的函数(opcount);对文件中的行进行简单的迭代(simplecount);带有内存映射文件(mmap)的readline(mapcount);以及Mykola Kharechko提供的缓冲区读取解决方案(bufcount)。

我运行每个函数五次,计算120万行文本文件的平均运行时间。

Windows XP、Python 2.5、2GB RAM、2 GHz AMD处理器

以下是我的结果:

mapcount : 0.465599966049
simplecount : 0.756399965286
bufcount : 0.546800041199
opcount : 0.718600034714

编辑:Python2.6的数字:

mapcount : 0.471799945831
simplecount : 0.634400033951
bufcount : 0.468800067902
opcount : 0.602999973297

因此,缓冲区读取策略似乎是Windows/Python 2.6中最快的

代码如下:

from __future__ import with_statement
import time
import mmap
import random
from collections import defaultdict

def mapcount(filename):
    f = open(filename, "r+")
    buf = mmap.mmap(f.fileno(), 0)
    lines = 0
    readline = buf.readline
    while readline():
        lines += 1
    return lines

def simplecount(filename):
    lines = 0
    for line in open(filename):
        lines += 1
    return lines

def bufcount(filename):
    f = open(filename)                  
    lines = 0
    buf_size = 1024 * 1024
    read_f = f.read # loop optimization

    buf = read_f(buf_size)
    while buf:
        lines += buf.count('\n')
        buf = read_f(buf_size)

    return lines

def opcount(fname):
    with open(fname) as f:
        for i, l in enumerate(f):
            pass
    return i + 1


counts = defaultdict(list)

for i in range(5):
    for func in [mapcount, simplecount, bufcount, opcount]:
        start_time = time.time()
        assert func("big_file.txt") == 1209138
        counts[func].append(time.time() - start_time)

for key, vals in counts.items():
    print key.__name__, ":", sum(vals) / float(len(vals))

再好不过了。

毕竟,任何解决方案都必须读取整个文件,计算出有多少个\n,并返回结果。

你有没有更好的方法在不读取整个文件的情况下做到这一点?不确定。。。最好的解决方案永远是I/O绑定,最好的方法是确保不使用不必要的内存,但看起来已经覆盖了。

相关问题 更多 >