Python:逐行读取文件的最佳方式

时间:2016-05-14 22:11:46

标签: python input

我有一个需要阅读的大型输入文件,因此我不想使用enumeratefo.readlines()for line in fo:以传统的方式行不通,我会说明原因,但我觉得对此的一些修改就是我现在所需要的。请考虑以下文件:

 input_file.txt:
 3 # No of tests that will follow
 3 # No of points in current test
 1 # 1st x-coordinate
 2 # 2nd x-coordinate
 3 # 3rd x-coordinate
 2 # 1st y-coordinate
 4 # 2nd y-coordinate
 6 # 3rd y-coordinate
 ...

我需要的是能够读取变量的行块,将元组中的坐标配对,将元组添加到案例列表中,然后返回到从文件中读取新案例。

我想到了这个:

with open(input_file) as f:
    T = int(next(f)) 
    for _ in range(T):
        N = int(next(f))
        for i in range(N):
            x.append(int(f.next()))
        for i in range(N):
            y.append(int(f.next()))

然后将两个列表耦合成一个元组。我觉得必须有一个更清洁的方法来做到这一点。有什么建议吗?

编辑:y坐标必须有一个单独的for循环才能读取。它们是x和y坐标分开n行。所以Read line i;读线(i + n);重复n次 - 对于每种情况。

3 个答案:

答案 0 :(得分:3)

这可能不是最短的解决方案,但我相信它“非常优秀”。

def parse_number(stream):
    return int(next(stream).partition('#')[0].strip())

def parse_coords(stream, count):
    return [parse_number(stream) for i in range(count)]

def parse_test(stream):
    count = parse_number(stream)
    return list(zip(parse_coords(stream, count), parse_coords(stream, count)))

def parse_file(stream):
    for i in range(parse_number(stream)):
        yield parse_test(stream)

它将急切地解析单个测试的所有坐标,但每个测试只会在你要求的时候懒得解析。

您可以像这样使用它来迭代测试:

if __name__ == '__main__':
    with open('input.txt') as istr:
        for test in parse_file(istr):
            print(test)

可能需要更好的函数名称来更好地区分渴望和懒惰函数。我现在缺乏命名创造力。

答案 1 :(得分:2)

grouper recipe

如何做到这一点
from itertools import zip_longest

def grouper(iterable, n, fillvalue=None):
    """Collect data into fixed-length chunks or blocks
        grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"""
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)

with open(input_file) as archi:
    T = int(next(archi))
    N = int(next(archi))
    points = [ g for g in grouper(map(int,archi),N) ]
    print(points) # [(1, 2, 3), (2, 4, 6)]
    result = list( zip(*points) )
    print(result) #  [(1, 2), (2, 4), (3, 6)]

这里我使用石斑鱼阅读N行,获取一个包含所有x和所有y的元组列表,然后使用zip将所有这些组合在一起

答案 2 :(得分:0)

听起来你并没有真正尝试“逐行读取文件”。听起来你想跳过文件,将其视为一个大型列表/数组,但不会引发过多的内存消耗。

你看过mmap模块了吗? 有了这个,您可以使用.find()之类的方法来查找换行符,可选择从某个偏移量开始(例如刚刚超过当前的测试头)和.seek()将文件指针移动到您找到的第n个项目然后是.readline()等等。

mmap对象共享字符串或字节数组的一些方法和属性,以及文件类对象中的一些方法和属性。因此,您可以使用混合的方法,如.find()(字符串和字节数组的常规)和.seek()(用于文件)。

此外,Python内存映射使用操作系统的功能将文件映射到内存中。 (在Linux和类似系统上,这与您的共享库映射到所有正在运行的进程的地址空间的机制相同)。关键是你的内存只用作文件内容的缓存,操作系统将透明地执行必要的I / O加载和释放文件内容的内存缓冲区。

我没有看到找到某个字符或字符串的“第n”个出现的方法......所以没有办法跳到某个行。据我所知,你必须循环.find()但是你可以使用Python的切片表示法跳回任何这样的行。您可以编写实用程序类/对象以一次扫描1000行终止符,并将它们存储在索引/列表中。然后,您可以使用内存映射切片中的值。

相关问题