当前位置: 首页 > 面试题库 >

如何在Python中逐行读取文件?

吕霍英
2023-03-14
问题内容

在史前时代(Python 1.4)中,我们做到了:

fp = open('filename.txt')
while 1:
    line = fp.readline()
    if not line:
        break
    print line

在Python 2.1之后,我们做到了:

for line in open('filename.txt').xreadlines():
    print line

在Python 2.3中获得便利的迭代器协议之前,它可以做到:

for line in open('filename.txt'):
    print line

我看过一些使用更详细的示例:

with open('filename.txt') as fp:
    for line in fp:
        print line

这是首选的方法吗?

[edit]我知道with语句可以确保关闭文件…但是为什么文件对象的迭代器协议中没有包含该语句呢?


问题答案:

偏爱以下原因的确有一个原因:

with open('filename.txt') as fp:
    for line in fp:
        print line

我们都为CPython的相对确定性的引用计数方案所迷惑。如果其他假设的Python实现with使用某种其他方案来回收内存,则没有块时不一定会“迅速”关闭文件。

在这样的实现中,如果您的代码打开文件的速度比垃圾收集器在孤立的文件句柄上调用终结器的速度快,则可能会从OS收到“打开太多文件”错误。通常的解决方法是立即触发GC,但这是一个讨厌的技巧,必须由可能遇到错误的
每个 函数(包括库中的函数)来完成。什么样的恶梦。

或者,您可以只使用with块。

奖金问题

(如果仅对问题的客观方面感兴趣,请立即停止阅读。)

为什么文件对象的迭代器协议中未包含该代码?

这是有关API设计的主观问题,因此我有两个部分的主观答案。

从直觉上讲,这是错的,因为它使迭代器协议执行两项独立的操作(遍历
关闭文件句柄),并且使外观简单的函数执行两项操作通常是个坏主意。在这种情况下,感觉特别糟糕,因为迭代器以准功能,基于值的方式与文件内容相关联,但是管理文件句柄是完全独立的任务。对于阅读代码的人来说,将两者无形地压为一个动作是令人惊讶的,并使推理程序行为变得更加困难。

其他语言基本上得出了相同的结论。Haskell简短地调侃了所谓的“惰性IO”,它允许您遍历文件并在到达流末尾时自动将其关闭,但是如今,在Haskell和Haskell中几乎普遍不鼓励使用惰性IO。用户大多转向更明确的资源管理,例如Conduit,其行为更像withPython中的块。

从技术上讲,您可能需要对Python中的文件句柄做一些事情,如果迭代关闭了文件句柄,这些操作将无法正常工作。例如,假设我需要遍历文件两次:

with open('filename.txt') as fp:
    for line in fp:
        ...
    fp.seek(0)
    for line in fp:
        ...

虽然这是一种不太常见的用例,但请考虑以下事实:我可能刚刚将底部的三行代码添加到了原来具有前三行的现有代码库中。如果迭代关闭了文件,我将无法执行该操作。因此,将迭代和资源管理分开保持可以更轻松地将代码块组合成一个更大的,可运行的Python程序。

可组合性是语言或API最重要的可用性功能之一。



 类似资料:
  • 问题内容: 我想遍历整个文件的每一行。一种方法是读取整个文件,将其保存到列表中,然后遍历感兴趣的行。此方法占用大量内存,因此我正在寻找替代方法。 到目前为止,我的代码: 执行此代码将显示错误消息:。 有什么建议么? 目的是计算成对的字符串相似度,这意味着对于文件中的每一行,我要计算每隔一行的距离。 问题答案: 正确的,完全Python的读取文件的方法如下: 该with语句处理文件的打开和关闭,包括

  • 问题内容: 在Java 8中,我看到在Files类中添加了一个名为lines()的新方法,该方法可用于在Java中逐行读取文件。它适用于大文件吗?我的意思是我们可以先加载1000行,然后加载第二组1000行。我有1GB的大文件,能用吗? 有人可以分享代码段的用法吗? 问题答案: 它适用于大文件吗?[…]我有1GB的大文件,能用吗? 据我所知,它也应适用于大文件(但我没有尝试过): 我的意思是我们可

  • 我试图在Perl6中逐行读取一个巨大的gz文件。 我正在尝试做这样的事情 但是这会给出一个错误,我有一个格式不正确的UTF-8。我看不到如何从帮助页面读取gzip材料https://docs.perl6.org/language/unicode#UTF8-C8或https://docs.perl6.org/language/io 我想完成和在Perl5中一样的事情:http://blog-en .

  • 我正在试着阅读我的文件的每一行,其中包含一个用户名列表,并用它创建一个登录系统。我正在尝试实现一个基本的登录系统,它的用户名存储在.txt文件中,但我的代码不工作,我不知道为什么。我认为问题出在检查用户名的循环中。 这是我的代码,但它不起作用,只是打印总是失败: 有什么想法吗?

  • 问题内容: 如何在Python中读取文件的每一行并将每一行存储为列表中的元素? 我想逐行读取文件并将每一行追加到列表的末尾。 问题答案:

  • 问题内容: 我在Go中找不到功能。我可以弄清楚如何快速编写一个,但是我只是想知道我是否在这里忽略了一些东西。如何逐行读取文件? 问题答案: _注意: 可接受的答案在早期的Go版本中是正确的。 包中有ReadLine函数。 请注意,如果该行不适合读取缓冲区,则该函数将返回不完整的行。如果要始终通过单次调用函数来读取程序中的整行,则需要将该函数封装到自己的函数中,该函数在for循环中进行调用。 之所以