Вопрос-Ответ

Iterating on a file doesn't work the second time [duplicate]

Повторение файла не работает во второй раз

У меня проблема с повторением файла. Вот что я ввожу в интерпретаторе и результат:

>>> 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() файл, а затем снова открыть его для чтения! Это нормальное поведение?

Переведено автоматически
Ответ 1

Да, это нормальное поведение. В основном вы читаете до конца файла в первый раз (вы можете представить это как чтение ленты), поэтому вы не сможете читать из него больше, пока не сбросите его, либо используя f.seek(0) для перемещения в начало файла, либо закрыв его, а затем снова открыв, что начнется с начала файла.

Если вы предпочитаете, вы можете использовать with синтаксис вместо этого, который автоматически закроет файл для вас.

например,

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

после завершения выполнения этого блока файл автоматически закрывается для вас, так что вы можете выполнить этот блок повторно, не закрывая файл явно самостоятельно, и прочитать файл таким образом снова.

Ответ 2

Когда объект file считывает файл, он использует указатель, чтобы отслеживать, где он находится. Если вы прочитаете часть файла, а затем вернетесь к нему позже, он продолжит с того места, на котором вы остановились. Если вы прочитаете весь файл целиком и вернетесь к тому же файловому объекту, это будет похоже на чтение пустого файла, потому что указатель находится в конце файла и читать больше нечего. Вы можете использовать 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
Ответ 3

Файловый объект является буфером. При чтении из буфера используется та часть, которую вы читаете (позиция чтения смещается вперед). Когда вы читаете весь файл, позиция чтения находится в конце файла (EOF), поэтому он ничего не возвращает, потому что читать больше нечего.

Если вам по какой-либо причине необходимо сбросить позицию чтения для файлового объекта, вы можете сделать:

f.seek(0)
Ответ 4

Конечно. Это нормальное поведение. Вместо закрытия и повторного открытия вы могли бы rewind открыть файл.

python file