Если вы читаете весь файл с помощью content = open('Path/to/file', 'r').read()
, то дескриптор файла остается открытым до выхода script? Есть ли более сжатый метод для чтения целого файла?
Чтение всего файла в Python
Ответ 1
Ответ на этот вопрос зависит от конкретной реализации Python.
Чтобы понять, о чем все это, обратите особое внимание на фактический объект file
. В вашем коде этот объект упоминается только один раз в выражении и становится недоступным сразу после возврата вызова read()
.
Это означает, что файловый объект является мусором. Единственный оставшийся вопрос - "Когда сборщик мусора соберет объект файла?".
в CPython, который использует счетчик ссылок, этот вид мусора замечается немедленно, и поэтому он будет немедленно собран. Обычно это не так для других реализаций Python.
Лучшее решение, чтобы убедиться, что файл закрыт, это шаблон:
with open('Path/to/file', 'r') as content_file:
content = content_file.read()
который всегда будет закрывать файл сразу после окончания блока; даже если происходит исключение.
Редактировать: чтобы поставить более тонкую точку на нем:
Кроме file.__exit__()
, который "автоматически" вызывается в настройке with
контекстным менеджером, единственный другой способ, которым file.close()
вызывается автоматически (то есть, кроме явного его вызова самостоятельно), - через file.__del__()
. Это приводит нас к вопросу о том, когда __del__()
?
Правильно написанная программа не может предполагать, что финализаторы когда-либо будут работать в любой момент до завершения программы.
- https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203
Особенно:
Объекты никогда не уничтожаются явно; однако, когда они становятся недоступными, они могут быть собраны мусором. Реализация может откладывать сборку мусора или вообще ее опускать - вопрос качества реализации в том, как реализована сборка мусора, до тех пор, пока не будут собраны объекты, которые все еще доступны.
[...]
CPython в настоящее время использует схему подсчета ссылок с (опционально) отложенным обнаружением циклически связанного мусора, который собирает большинство объектов, как только они становятся недоступными, но не гарантирует сбор мусора, содержащего циклические ссылки.
- https://docs.python.org/3.5/reference/datamodel.html#objects-values-and-types
(Акцент мой)
но, как предполагается, другие реализации могут иметь другое поведение. Например, в PyPy есть 6 разных реализаций сборки мусора !
Ответ 2
Вы можете использовать pathlib.
Для Python 3.5 и выше:
from pathlib import Path
contents = Path(file_path).read_text()
Для более низких версий Python используйте pathlib2:
$ pip install pathlib2
Затем:
from pathlib2 import Path
contents = Path(file_path).read_text()
Это фактическая реализация read_text
:
def read_text(self, encoding=None, errors=None):
"""
Open the file in text mode, read it, and close the file.
"""
with self.open(mode='r', encoding=encoding, errors=errors) as f:
return f.read()