Python 中“while not EOF”的完美对应物是什么 [duplicate]

What is the perfect counterpart in Python for "while not EOF" [duplicate]

提问人:Allen Koo 提问时间:3/24/2013 最后编辑:cs95Allen Koo 更新时间:10/8/2022 访问量:444698

问:

要读取一些文本文件,在 C 或 Pascal 中,我总是使用以下代码片段来读取数据,直到 EOF:

while not eof do begin
  readline(a);
  do_something;
end;

因此,我想知道如何在 Python 中简单快速地做到这一点?

Python 文件 迭代 EOF

评论

0赞 Karl Knechtel 9/3/2022
我选择了另一个问题作为规范,因为问题陈述显然更好:“在 X 语言中与在 Z 语言中做 Y 的对应物是什么”是问“我该如何做(Y 在 Z 语言中做的事情)在 X 语言中”的劣质方式。用 X 语言寻求帮助的人不应该为了确认他们找到了正确的问题而理解 Z 语言,问题的标题应该以与语言无关的方式清楚地说明问题的内容。

答:

244赞 Martijn Pieters 3/24/2013 #1

遍历文件以读取行:

with open('somefile') as openfileobject:
    for line in openfileobject:
        do_something()

文件对象是可迭代的,并在 EOF 之前产生行。将文件对象用作可迭代对象使用缓冲区来确保高性能读取。

您可以对 stdin 执行相同的操作(无需使用:raw_input()

import sys

for line in sys.stdin:
    do_something()

为了完成这幅画,可以使用以下方式完成二进制读取:

from functools import partial

with open('somefile', 'rb') as openfileobject:
    for chunk in iter(partial(openfileobject.read, 1024), b''):
        do_something()

where 一次最多包含文件中的 1024 个字节,当开始返回空字节字符串时,迭代停止。chunkopenfileobject.read(1024)

评论

8赞 ben_joseph 7/12/2017
注意:末尾将有一个换行符。line
1赞 LtWorf 10/15/2017
对于通用二进制文件来说,读取行有点危险,因为也许你有 6GiB 长的行......
0赞 Martijn Pieters 10/15/2017
@LtWorf:这就是为什么我展示了如何以块而不是行的形式读取二进制文件。
0赞 Charlie Parker 2/25/2019
我正在从正在运行的进程中读取...所以在我杀死进程之前,它永远不会有 EOF。但后来我到了“到现在结束”,我陷入了僵局。如何检测这一点而不是死锁?就像没有新行一样,停止读取文件(即使没有 EOF,在我的情况下永远不会存在)。stdin
0赞 Martijn Pieters 2/25/2019
@CharlieParker:如果遇到死锁,那么可能是忘记了刷新缓冲区。如果没有实际的 MCVE,很难再说什么了。
20赞 NPE 3/24/2013 #2

打开文件并逐行读取的 Python 习惯用法是:

with open('filename') as f:
    for line in f:
        do_something(line)

该文件将在上述代码的末尾自动关闭(构造负责)。with

最后,值得注意的是,这将保留尾随换行符。这可以通过以下方法轻松删除:line

line = line.rstrip()

评论

1赞 jedwards 3/24/2013
+1,还向 OP 指出这与非常相似的 ,一个通常建议的解决方案不同。for line in f.readlines(): ...
78赞 dawg 3/24/2013 #3

您可以在 Python 中模仿 C 习语。

要读取最多 (>0) 个字节数的缓冲区,可以执行以下操作:max_size

with open(filename, 'rb') as f:
    while True:
        buf = f.read(max_size)
        if buf == 0:
            break
        process(buf)

或者,逐行查看文本文件:

# warning -- not idiomatic Python! See below...
with open(filename, 'rb') as f:
    while True:
        line = f.readline()
        if not line:
            break
        process(line)

您需要使用构造,因为 Python 中没有 eof 测试,除了缺少从读取返回的字节之外。while True / break

在 C 语言中,您可能具有:

while ((ch != '\n') && (ch != EOF)) {
   // read the next ch and add to a buffer
   // ..
}

但是,您不能在 Python 中使用此功能:

 while (line = f.readline()):
     # syntax error

因为 Python 中的表达式中不允许赋值(尽管最新版本的 Python 可以使用赋值表达式来模拟这一点,请参见下文)。

在 Python 中,这样做当然习惯:

# THIS IS IDIOMATIC Python. Do this:
with open('somefile') as f:
    for line in f:
        process(line)

更新:从 Python 3.8 开始,您还可以使用赋值表达式

 while line := f.readline():
     process(line)

即使读取的行为空并持续到 EOF,这也有效。

评论

3赞 CODE-REaD 5/14/2016
作为一名 C 和 Perl 程序员,您关于表达式中不允许赋值的观点对我来说至关重要。
2赞 Donald Smith 3/14/2017
当您每次迭代需要对多个输入行进行操作时,“while True:”方法也很有用,这是惯用的 Python 不允许的(据我所知,无论如何)。
0赞 LtWorf 10/15/2017
如果你不对文件做出假设,你就不应该阅读行。二进制文件可能有大行...
1赞 flow2k 5/29/2019
非惯用方式似乎有一个优势:您可以进行细粒度的错误处理,例如 catch ,这是惯用迭代无法做到的。readline()UnicodeDecodeErrorfor
1赞 rrrrrrrrrrrrrrrr 10/8/2022
请注意,从 Python 3 开始,该示例不正确:当非阻塞缓冲区当前没有可提供的数据时返回,并且不指示已达到 EOF。为此,使用返回值 。我已就此提出编辑建议。docs.python.org/3/library/io.html#io.RawIOBase.read.readreadNone0
14赞 A R 10/27/2014 #4

您可以使用下面的代码片段逐行阅读,直到文件末尾

line = obj.readline()
while(line != ''):

    # Do Something

    line = obj.readline()

评论

0赞 Jonathan Starr 8/10/2018
通常,遍历这些行会扭曲程序的结构。例如,在语言分析器中,您希望读取行并按顺序处理它们。您不想仅仅为了循环读取行,然后将它们发送到解析器而重新构建顶层。
1赞 Aditeya Pandey 3/9/2015 #5

您可以使用以下代码片段。readlines() 一次读取整个文件并按行拆分。

line = obj.readlines()
13赞 user5472996 10/22/2015 #6

虽然上面有关于“以 python 方式做”的建议,但如果真的想有一个基于 EOF 的逻辑,那么我想使用异常处理是做到这一点的方法——

try:
    line = raw_input()
    ... whatever needs to be done incase of no EOF ...
except EOFError:
    ... whatever needs to be done incase of EOF ...

例:

$ echo test | python -c "while True: print raw_input()"
test
Traceback (most recent call last):
  File "<string>", line 1, in <module> 
EOFError: EOF when reading a line

或按提示符(Windows、Linux)Ctrl-Zraw_input()Ctrl-Z

3赞 Yam Mesicka 7/30/2020 #7

除了 @dawg 的精彩回答之外,使用 walrus 运算符 (Python >= 3.8) 的等效解决方案:

with open(filename, 'rb') as f:
    while buf := f.read(max_size):
        process(buf)
0赞 Ali Sajjad 6/5/2021 #8

这个怎么样!让一切变得简单!

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

无需浪费额外的线路。并且无需使用关键字,因为当没有文件对象的引用时,文件将自动关闭。with

评论

0赞 Karol S 11/28/2022
并非所有 Python 实现都使用引用计数,因此应始终使用引用计数,但仅打开一个或两个文件然后退出的短期脚本除外。with
0赞 Ali Sajjad 11/29/2022
@KarolS你的意思是只有较新版本的 Python 才能进行引用计数?
1赞 Karol S 11/29/2022
不,我的意思是确切的垃圾回收方法因实现而异。CPython 使用引用计数,因此文件将在循环后立即关闭,但 Pypy、Jython、IronPython 和 Brython 不使用它,并且文件可能会保持打开状态,直到程序终止。