有没有办法从python中的文件读取10000行?

时间:2012-06-18 21:05:02

标签: python

我在python中相对较新,正在研究C语言。因为我在python中看到了许多我不知道的新函数,所以我想知道是否有一个函数可以从python中的文件请求10000行。

如果存在这种功能,我会期待这样的事情:

lines = get_10000_lines(file_pointer)

python是否有内置功能,或者我可以为此下载任何模块吗? 如果没有,我该如何做到这一点是最简单的方法。我需要分析一个巨大的文件,所以我想读取10000行并分析每次以节省内存。

感谢您的帮助!

8 个答案:

答案 0 :(得分:22)

  

f.readlines()返回一个包含文件中所有数据行的列表。如果给定一个可选的参数sizehint,它会从文件读取多个字节,并且足以完成一行,并从中返回行。这通常用于允许按行有效读取大文件,但无需将整个文件加载到内存中。只返回完整的行。

来自the docs

这并不是你要求的,因为这限制了读取的字节数而不是读取的行数,但我认为这是你想要做的事情。

答案 1 :(得分:21)

from itertools import islice

with open(filename) as f:
    first10000 = islice(f, 10000)

这会将first10000设置为可迭代对象,即您可以使用

循环它
for x in first10000:
    do_something_with(x)

如果您需要列表,请改为list(islice(f, 10000))

当文件包含少于10k行时,这将返回文件中的所有行,没有填充(与基于range的解决方案不同)。当以块的形式读取文件时,结果中的< 10000行会发出EOF信号:

with open(filename) as f:
    while True:
        next10k = list(islice(f, 10000))  # need list to do len, 3 lines down
        for ln in next10k:
            process(ln)
        if len(next10k) < 10000:
            break

答案 2 :(得分:5)

你真的关心你一次有多少行吗?通常最有意义的是逐行迭代文件对象:

f = open('myfile.txt', 'r')
for line in f:
    print line

python文档表明这是处理文件的首选方法:

  

读取行的另一种方法是遍历文件对象。这样可以节省内存,速度快,并且可以使代码更简单。

有关示例,请参阅python docs

答案 3 :(得分:3)

只需打开文件,告诉Python读取一行10,000次。

lines = None
with open('<filename>') as file:
    lines = (file.readline() for i in range(10000))

答案 4 :(得分:3)

确定文件对于内存来说太大了吗?

由于函数调用有开销(即调用相同的函数10000次很慢)并且内存很便宜,我建议一次读取所有行,然后切换到结果列表中。如果您想稍后处理下一个10000,这当然是最快的方式 - 它们将立即为您做好准备。

with open("filename") as f:
    lines = f.readlines()

indices = range(0, len(lines), 10000) + [len(lines)]
for start, stop in zip(indices, indices[1:]):
    do_stuff_with(lines[start:stop])

当然,如果文件不适合空闲内存,那么这将无效。如果是这样的话,我会选择ChipJust's answer。您甚至可以使用readlines sizehint,tellseek创建一个追求目标的功能,如果这很重要的话,它将在10000条线路上“归属”。

答案 5 :(得分:3)

f = open('myfile.txt', 'r')
while True:
    bytes_lines = f.readlines(10000) # read no more than 10000 bytes
    if not bytes_lines: break # stop looping if no lines read
    for line in bytes_lines:
        text = line.decode("knownencoding") # text will be a unicode object

一次读取大量文本然后处理它会更快。这会读取大量文本,然后将其拆分为多行。这节省了读取。它也只会给你完整的行,所以你不需要处理连接行的存根。

进行测试以确保从已经存在的文件中读取不会引发异常。

答案 6 :(得分:3)

没有任何功能可以按照您的意愿运行。你可以轻松地写一个,但你可能不会更好。例如,如果您获得这里显示的许多解决方案的行列表,那么您必须分别分析每一行:

def get_10000_lines(f):
    while True:
        chunk = list(itertools.islice(f, 10000))
        if not chunk:
            break
        yield chunk

如果你这样做,你也可以一次只读取一行文件,并分析每个字符串。无论如何,文件I / O都将被缓冲:

for line in f:
    analyze_the_line(line)

如果你想要一个包含10,000行的字符串,那么你将单独阅读每一行并将它们连接在一起:

for chunk in get_10000_lines(f):
    str_10k = "".join(chunk)
    analyze_a_bunch(str_10k)

现在你正在做很多分配和连接字符串的工作,这可能不值得。

如果你可以对部分行进行分析,那么最好是你可以用1Mb块读取文件:

while True:
    chunk = f.read(1000000)
    if not chunk:
        break
    analyze_a_bunch(chunk)

答案 7 :(得分:3)

从几个other solutions中抽取,但​​添加了一个扭曲......

>>> with open('lines.txt', 'r') as lines:
...     chunks = iter(lambda: list(itertools.islice(lines, 7)), [])
...     for chunk in chunks:
...         print chunk
... 
['0\n', '1\n', '2\n', '3\n', '4\n', '5\n', '6\n']
['7\n', '8\n', '9\n', '10\n', '11\n', '12\n', '13\n']
['14\n', '15\n', '16\n', '17\n', '18\n', '19\n', '20\n']
['21\n', '22\n', '23\n', '24\n', '25\n', '26\n', '27\n']
['28\n', '29\n', '30\n', '31\n', '32\n', '33\n', '34\n']
['35\n', '36\n', '37\n', '38\n', '39\n', '40\n', '41\n']
['42\n', '43\n', '44\n', '45\n', '46\n', '47\n', '48\n']
['49\n', '50\n', '51\n', '52\n', '53\n', '54\n', '55\n']
['56\n', '57\n', '58\n', '59\n', '60\n', '61\n', '62\n']
['63\n', '64\n', '65\n', '66\n', '67\n', '68\n', '69\n']
['70\n', '71\n', '72\n', '73\n', '74\n', '75\n', '76\n']
['77\n', '78\n', '79\n', '80\n', '81\n', '82\n', '83\n']
['84\n', '85\n', '86\n', '87\n', '88\n', '89\n', '90\n']
['91\n', '92\n', '93\n', '94\n', '95\n', '96\n', '97\n']
['98\n', '99\n']

但在这里我必须承认,正如其他人所说,只要你不需要完全 10000行(或10000),使用带有字节提示的readlines就会快一点每次都行)。但是,我不相信这是因为它的读取次数较少。 readlines docstring说“重复调用readline()并返回如此读取的行列表。”所以我认为速度增益来自于削减一些少量的迭代器开销。定义(使用Marcin的代码):

def do_nothing_islice(filename, nlines):
    with open(filename, 'r') as lines:
        chunks = iter(lambda: list(itertools.islice(lines, nlines)), [])
        for chunk in chunks:
            chunk

def do_nothing_readlines(filename, nbytes):
    with open(filename, 'r') as lines:
        while True:
            bytes_lines = lines.readlines(nbytes)
            if not bytes_lines:
                break
            bytes_lines

试验:

>>> %timeit do_nothing_islice('lines.txt', 1000)
10 loops, best of 3: 63.6 ms per loop
>>> %timeit do_nothing_readlines('lines.txt', 7000) # 7-byte lines, ish
10 loops, best of 3: 56.8 ms per loop
>>> %timeit do_nothing_islice('lines.txt', 10000)
10 loops, best of 3: 58.4 ms per loop
>>> %timeit do_nothing_readlines('lines.txt', 70000) # 7-byte lines, ish
10 loops, best of 3: 50.7 ms per loop
>>> %timeit do_nothing_islice('lines.txt', 100000)
10 loops, best of 3: 76.1 ms per loop
>>> %timeit do_nothing_readlines('lines.txt', 700000) # 7-byte lines, ish
10 loops, best of 3: 70.1 ms per loop

在平均线长7(逐行打印0 - > 1000000)的文件上,使用带有大小提示的readlines会更快一点。但只是一点点。还要注意奇怪的缩放 - 我不明白那里发生了什么。