#python #file
Вопрос:
Для упражнения, которое я выполняю, я пытаюсь прочитать содержимое данного файла дважды, используя этот 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: Закрытие и повторное открытие файла не всегда является хорошей идеей, так как это может иметь другие последствия в системе (временные файлы, инкрон и т.д.).
4. Я просто хочу констатировать очевидное: Вы дважды вызывали read ()!
5. W/R/T/ S. Лотт, и начиная с 5 лет: это действительно должно быть в документации по python. Не очевидно, что следует предполагать, что чтение файлового объекта изменит состояние чего-либо, особенно если вы привыкли работать с неизменяемыми данными/программированием в функциональном стиле…
Ответ №1:
Вызов read()
считывает весь файл и оставляет курсор чтения в конце файла (больше читать нечего). Если вы хотите прочитать определенное количество строк за один раз , вы можете использовать readline()
readlines()
или перебирать строки с for line in handle:
помощью .
Чтобы ответить на ваш вопрос напрямую, как только файл был прочитан, read()
вы можете использовать seek(0)
для возврата курсора чтения в начало файла (документы здесь). Если вы знаете, что файл не будет слишком большим, вы также можете сохранить read()
выходные данные в переменной, используя их в своих findall
выражениях.
Пс. Не забудьте закрыть файл после того, как закончите с ним.
Комментарии:
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:
Я всегда нахожу метод чтения чем — то вроде прогулки по темному переулку. Вы спускаетесь немного вниз и останавливаетесь, но если вы не считаете свои шаги, вы не уверены, как далеко вы продвинулись. Поиск дает решение путем изменения положения, другой вариант-указать, который возвращает положение вдоль файла. Возможно,API файлов Python может объединить чтение и поиск в read_from(позиция, байты), чтобы упростить его — пока это не произойдет, вы должны прочитать эту страницу.