57

我在迭代文件时遇到问题。这是我在解释器上输入的内容和结果:

>>> f = open('baby1990.html', 'rU')
>>> for line in f.readlines():
...  print(line)
... 
# ... all the lines from the file appear here ...

当我再次尝试迭代同一个打开的文件时,我什么也得不到!

>>> for line in f.readlines():
...  print(line)
... 
>>>

根本没有输出。为了解决这个问题,我必须close()打开文件然后再次打开它以供阅读!这是正常的行为吗?

4

4 回答 4

89

是的,这是正常行为。你基本上是第一次读到文件的末尾(你可以把它想象成在读磁带),所以除非你重置它,否则你不能再从它读取,通过使用f.seek(0)重新定位到开头文件,或者关闭它然后再次打开它,这将从文件的开头开始。

如果您愿意,可以改用with语法,它会自动为您关闭文件。

例如,

with open('baby1990.html', 'rU') as f:
  for line in f:
     print line

一旦这个块执行完毕,文件会自动为你关闭,所以你可以重复执行这个块,而不用自己明确地关闭文件,然后再次以这种方式读取文件。

于 2012-04-21T01:02:59.937 回答
17

当文件对象读取文件时,它使用一个指针来跟踪它的位置。如果您阅读了文件的一部分,然后稍后再返回,它将从您离开的地方继续。如果你读取整个文件,然后回到同一个文件对象,这就像读取一个空文件,因为指针在文件的末尾,没有任何东西可以读取。您可以使用file.tell()查看指针在文件中的位置并file.seek设置指针。例如:

>>> file = open('myfile.txt')
>>> file.tell()
0
>>> file.readline()
'one\n'
>>> file.tell()
4L
>>> file.readline()
'2\n'
>>> file.tell()
6L
>>> file.seek(4)
>>> file.readline()
'2\n'

此外,您应该知道file.readlines()读取整个文件并将其存储为列表。这很有用,因为您可以替换:

for line in file.readlines():
    #do stuff
file.seek(0)
for line in file.readlines():
    #do more stuff

和:

lines = file.readlines()
for each_line in lines:
    #do stuff
for each_line in lines:
    #do more stuff

您还可以一次一行地遍历一个文件,而无需将整个文件保存在内存中(这对于非常大的文件非常有用),方法是:

for line in file:
    #do stuff
于 2012-04-21T01:05:29.907 回答
9

文件对象是一个缓冲区。当您从缓冲区读取时,您读取的那部分将被消耗(读取位置向前移动)。当您通读整个文件时,读取位置位于文件末尾 (EOF),因此它不返回任何内容,因为没有任何内容可供读取。

如果由于某种原因必须重置文件对象的读取位置,您可以执行以下操作:

f.seek(0)
于 2012-04-21T01:04:34.037 回答
-1

当然。这是正常和理智的行为。而不是关闭和重新打开,你可以rewind文件。

于 2012-04-21T01:02:36.717 回答