#python
#python #io
Вопрос:
Для упражнения, которое я выполняю, я пытаюсь дважды прочитать содержимое данного файла, используя read()
метод. Как ни странно, когда я вызываю его во второй раз, он, похоже, не возвращает содержимое файла в виде строки?
Вот код
f = f.open()
# get the year
match = re.search(r'Popularity in (d )', f.read())
if match:
print match.group(1)
# get all the names
matches = re.findall(r'<td>(d )</td><td>(w )</td><td>(w )</td>', f.read())
if matches:
# matches is always None
Конечно, я знаю, что это не самый эффективный или лучший способ, здесь дело не в этом. Дело в том, почему я не могу вызвать read()
дважды? Нужно ли сбрасывать дескриптор файла? Или закрыть / повторно открыть файл, чтобы сделать это?
Комментарии:
1. Откуда вы взяли идею, что чтение не изменит состояние файла? Какую ссылку или учебник вы используете?
2. Я считаю, что закрытие и повторное открытие файла должны работать на основе приведенных ниже ответов.
3. @Shynthriir: закрытие и повторное открытие файла не всегда хорошая идея, поскольку это может иметь другие последствия в системе (временные файлы, incron и т. Д.).
4. Я просто хочу констатировать очевидное: вы дважды вызывали read()!
5. W / R / T / S.Лотт, и начиная с 5 лет: это действительно должно быть в документации python. Не очевидно, что следует предполагать, что чтение объекта file изменит состояние чего-либо, особенно если вы привыкли работать с неизменяемыми данными / программированием в функциональном стиле…
Ответ №1:
Вызов read()
считывает весь файл и оставляет курсор чтения в конце файла (больше читать нечего). Если вы хотите прочитать определенное количество строк за раз, вы можете использовать readline()
readlines()
или выполнять итерации по строкам for line in handle:
.
Чтобы ответить на ваш вопрос напрямую, после того, как файл был прочитан, with read()
вы можете использовать seek(0)
для возврата курсора чтения в начало файла (документы здесь). Если вы знаете, что файл не будет слишком большим, вы также можете сохранить read()
выходные данные в переменную, используя ее в своих findall
выражениях.
Ps. Не забудьте закрыть файл после того, как закончите с ним.
Комментарии:
1. 1, да, пожалуйста, прочитайте во временную переменную, чтобы избежать ненужного ввода-вывода файла. Это ложная экономия, что вы экономите память, потому что у вас меньше (явных) переменных.
2. @NickT: Я бы ожидал, что небольшой файл, считываемый несколько раз, кэшируется ОС (по крайней мере, в Linux / OSX), поэтому нет дополнительного ввода-вывода файлов для чтения дважды. Большие файлы, которые не помещаются в память, не кэшируются, но вы не хотите считывать их в переменную, потому что вы начнете менять местами. Поэтому в случае сомнений всегда читайте несколько раз. Если вы точно знаете, что файлы маленькие, делайте все, что дает самую приятную программу.
3. Удаление можно автоматизировать с помощью .
with
Ответ №2:
Как предлагалось в других ответах, вы должны использовать seek()
.
Я просто напишу пример:
>>> a = open('file.txt')
>>> a.read()
#output
>>> a.seek(0)
>>> a.read()
#same output
Ответ №3:
Все, кто до сих пор отвечал на этот вопрос, абсолютно правы — read()
перемещается по файлу, поэтому после того, как вы его вызвали, вы не можете вызвать его снова.
Что я добавлю, так это то, что в вашем конкретном случае вам не нужно возвращаться к началу или повторно открывать файл, вы можете просто сохранить прочитанный текст в локальной переменной и использовать его дважды или столько раз, сколько захотите, в своей программе:
f = f.open()
text = f.read() # read the file into a local variable
# get the year
match = re.search(r'Popularity in (d )', text)
if match:
print match.group(1)
# get all the names
matches = re.findall(r'<td>(d )</td><td>(w )</td><td>(w )</td>', text)
if matches:
# matches will now not always be None
Комментарии:
1. 1 На самом деле это было предлагаемое решение для этого упражнения ( code.google.com/intl/de-DE/edu/languages/google-python-class /… ). Но почему-то я не подумал о сохранении строки в переменной. Ого!
2. В Python3 используйте pathlib.
from pathlib import Path; text = Path(filename).read_text()
Заботится об открытии, закрытии и т. Д.
Ответ №4:
Указатель чтения перемещается на после последнего прочитанного байта / символа. Используйте seek()
метод для перемотки указателя чтения на начало.
Ответ №5:
Каждый открытый файл имеет соответствующую позицию.
Когда вы читаете (), вы читаете с этой позиции. Например read(10)
, считывает первые 10 байт из вновь открытого файла, затем другой read(10)
считывает следующие 10 байт. read()
без аргументов считывает все содержимое файла, оставляя позицию файла в конце файла. При следующем вызове read()
читать нечего.
Вы можете использовать seek
для перемещения позиции файла. Или, возможно, лучше в вашем случае было бы сделать один read()
и сохранить результат для обоих поисков.
Ответ №6:
read()
потребляет. Итак, вы можете сбросить файл или выполнить поиск в начале перед повторным чтением. Или, если это соответствует вашей задаче, вы можете использовать read(n)
для использования только n
байты.
Ответ №7:
Я всегда нахожу метод read чем-то вроде прогулки по темному переулку. Вы немного опускаетесь и останавливаетесь, но если вы не считаете свои шаги, вы не уверены, насколько далеко продвинулись. Поиск дает решение путем изменения положения, другой вариант — Tell, который возвращает позицию вдоль файла. Возможно, файловый API Python может объединять чтение и поиск в read_from(позиция, байты), чтобы упростить задачу — пока это не произойдет, вы должны прочитать эту страницу.