在跟踪行偏移以供将来参考的同时逐行读取文件的更有效的 Python 方法是什么?

What's a more efficient Pythonic method to read a file line-by-line while tracking line offsets for future reference?

提问人:Edward Falk 提问时间:8/29/2023 最后编辑:prabu nareshEdward Falk 更新时间:8/30/2023 访问量:70

问:

我想逐行读取文件,记下每行的文件偏移量,以便稍后可以返回。

我是这样手动完成的:

while True:
    offset = ifile.tell()
    line = ifile.readline()
    if not line: break
    ...

但它看起来很笨拙,似乎很慢。有没有更好、更像python的方法来做到这一点?

Python IO

评论

1赞 nneonneo 8/29/2023
我不明白为什么这很笨拙或缓慢。实际上,任何遍历行的方法最终都会在循环中调用 readline();与一般的 readline() 和 I/O 相比,tell() 的成本应该相当低。听起来您可能过早地进行了优化。
2赞 JL Peyret 8/29/2023
我很久以前就遇到过这个问题。由于缓冲,似乎在文本模式下并不那么可靠(这是在 2.7 上,但被标记为也不太可能在 3 上工作)。请参见 stackoverflow.com/a/46716840/1394353。YMMV。tell

答:

-1赞 prabu naresh 8/29/2023 #1
with open('your_file.ps', 'r') as ifile:
    page_offsets = []
    while True:
        offset = ifile.tell()
        line = ifile.readline()
        if not line:
            break
        if line.startswith(b'%%Page:'):
            page_offsets.append(offset)

# Now 'page_offsets' contains the file offsets of each %%Page: directive

    

评论

0赞 Edward Falk 8/29/2023
我认为返回行号。我希望实际的文件偏移量。这个想法是我正在处理一个 postscript 文件,并记下每个指令的位置,以便我以后可以返回它们。enumerate()%%Page:
0赞 prabu naresh 8/29/2023
如果您需要获取实际的文件偏移量而不是行号,则可以使用文件对象的 tell() 方法实现此目的。请参阅上面编辑的代码
1赞 nneonneo 8/29/2023
这与发布的 OP 代码相同;这个答案的价值是什么?
0赞 Hermann12 8/29/2023 #2

我会这样做:

with open('myfile.txt', 'r') as file:
    Lines = file.readlines()
        
count = 0
for line in Lines:
    count += 1
    print("Line{}: {}".format(count, line.strip()))
0赞 Mike Müller 8/30/2023 #3

您可以将文件对象用作迭代器:

def find_page_offsets(fname):
    page_offsets = []
    offset = 0
    with open(fname, 'rb') as fobj:
        for line in fobj:
            if line.startswith(b'%%Page:'):
                page_offsets.append(offset)
            offset += len(line)
    return page_offsets

请注意,这在循环中不起作用。因此,您需要使用并将其添加到 .此外,您需要以二进制模式打开文件,以避免在 Windows 上自动换行。fobj.tell()len(line)offset

评论

0赞 Edward Falk 9/1/2023
fobj.tell()似乎在循环中对我来说效果很好。@prabu naresh 下面的代码几乎与我最终编写的内容一字不差。我意识到在使用 utf-8 和 Windows 行尾时,文件偏移量存在一些棘手的问题,但我只在行的开头抓取文件偏移量并使用该值返回到文件中的同一点,到目前为止它工作得很好。
0赞 Edward Falk 9/1/2023
哦,等等。你指的是不能很好地使用文件迭代器。我在其他地方看到过。幸运的是,在这种情况下我没有使用迭代器。tell()
0赞 Mike Müller 9/3/2023
您是否检查了迭代器方法的运行时间和用例的循环?对于我的用例来说,迭代器通常要快得多。while True
0赞 Edward Falk 9/4/2023
我没有计时,但做循环而不是迭代器感觉更慢;这就是为什么我希望有一个使用迭代器的解决方案。也就是说,“感觉更慢”根本不是数据,所以老实说我不知道它是否更慢。我想我应该实际测试一下。