2009-09-03 2 views
10

Чтобы прочитать содержимое файла:Файл открыт: Является ли этот плохой стиль Python?

data = open(filename, "r").read() 

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

EDIT: Это на самом деле укусило меня в проекте, который я написал - мне было предложено задать вопрос this. Файловые объекты очищаются только тогда, когда у вас закончилась нехватка памяти, а не когда закончились файлы. Поэтому, если вы делаете это слишком часто, у вас может закончиться нехватка дескрипторов файлов и заставить ваши попытки ввода-вывода открывать файлы для исключения исключений.

+3

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

+0

@balpha: Но ответы противоречат друг другу. ;) (Я полагаю, вы сделали комментарий, прежде чем все ответы были в нем.) –

ответ

29

Только для записи: Это лишь немного больше, и немедленно закрывает файл:

from __future__ import with_statement 

with open(filename, "r") as f: 
    data = f.read() 
+4

+1 Я добавил 'import' на всякий случай, если они используют Python 2.5 :) –

+0

Вопрос о следующем стиле: неудивительно делать * с открытым (« t1.py »,« r ») как f: f. read() * все на одной строке? Я знаю, что это не так читаемо, но так часто чтение в файле очень простое, и следующий парень, читающий код, действительно не заботится о том, как вы это сделали. –

+0

@Jenn D: Одна точка «с» заключается в том, чтобы ограничить всю обработку в аккуратной области. Полагая 'с open() как f: f.read()' в одну строку сортирует поражение цели определения 'with'. –

3

Нет, это вполне разумный ИМО-метод Python, согласно вашим рассуждениям.

Обновление: Здесь есть много комментариев о том, будут ли убирать файлы прямо сейчас или нет. Вместо того, чтобы спекулировать, я сделал кое-что. Вот что я вижу:


Из комментария в object.h Пайтона:

макросы Py_INCREF (оп) и Py_DECREF (оп) используются для увеличения или ссылки декремент имеет значение. Py_DECREF называет deallocator объекта функцию, когда RefCount падает до 0

Глядя в fileobject.c Пайтона:

Функция таблицы для файла объектов точек, чтобы функционировать file_dealloc. Эта функция вызывает close_the_file, что, в свою очередь, закрывает файл.


Итак, представляется разумным указать, что на данный момент на CPython, когда нет дополнительных ссылок на файл-объект, он закрыт без каких-либо задержек. Если вы считаете, что это толкование неверно, напишите комментарий, указывающий, почему вы так себя чувствуете.

+0

Разумным, но ресурсы ОС могут быть недоступны, как вам хотелось бы. Например, попытка удалить файл сразу после прочтения может не сработать, поскольку ресурсы ОС хранятся в базовых библиотеках C, даже считая, что объект '' '' '' '' '' '' '' '' '' '' '' '' 'был собран. Пока ОС не подумает, что файл больше не используется, вы не сможете его удалить. –

+0

@ S. Лотт: вы говорите, что объект 'file', собранный мусором, не закрыт (так что ОС знает, что он больше не используется)? Я бы * ожидал *, что удаление объекта файла закрывает файл, но я ничего не могу найти в документации. – EOL

+5

Мое понимание заключается в том, что CPython (эталонная реализация, которую большинство людей думает, когда думает Python) действительно уничтожает все объекты без ссылок, поскольку они оставляют область видимости. В этом случае объект файла покидает область действия, как только операция read() завершается. Поэтому он должен делать именно то, что вы хотите. Однако это не гарантированное поведение. Другие реализации Python (Jython, я думаю, является ярким примером) могут обрабатывать сборку мусора по-разному. Мой инстинкт заключается в использовании простой реализации, если вы знаете, что используете CPython и не заботитесь о переносимости. –

1

выглядит хорошо для меня .. Я часто читаю такие файлы.

6

Это правда, что он в конце концов закроется, но в конце концов может быть не так скоро. Особенно, если вы используете это внутри цикла, система может закончиться файловыми дескрипторами, прежде чем GC попадет в объекты файла.

+0

О, никогда не думал об этом! – Claudiu

+0

Но если fileobj ссылается на ссылку .. он сразу переходит в 0 и сразу же удаляется? В CPython (?). – u0b34a0f6ae

+0

@ kaizer.se: он по-прежнему не обязательно удаляется сразу. только когда CPython нуждается в некоторой памяти. – Claudiu

4

код работает точно так же, как вы говорите, это делает, но это плохой стиль, тем не менее. Ваш код основывается на предположениях, которые могут быть истинными сейчас, но не всегда будут истинными. Не исключено, что ваш код будет запущен в ситуации, когда файл открывается и не закрывается. делает вопрос. Действительно ли это стоит того, чтобы сэкономить 1 или 2 строки кода? Я так не думаю.

2

Несмотря на то, что работает, как и ожидалось, я думаю, что он не в двух случаях:

  1. Ваш код не будет масштабироваться до бесшовно, потому что вы читаете весь файл в память, и это может или не может быть обязательно, что вы хотите.
  2. Согласно Zen of Python (попробуйте import this в приглашении Python для его получения) «явное лучше, чем неявное», и, неявно закрыв файл, вы можете смутить кого-то, кто по дороге останется с вашим кодом для обслуживания.

Это действительно помогает быть явным! Python поощряет явный стиль.

Помимо этого, для сценария с отбрасыванием ваш стиль имеет смысл.

Возможно, вы получите от this answer.

Смежные вопросы