Закрывает ли открытие файла как часть конструкции словаря его впоследствии? - PullRequest
0 голосов
/ 14 апреля 2020

Я видел этот синтаксис, когда имел дело с библиотекой запросов Python:

body = { file_name: open(file_path, 'rb') }

Интересно, закрывает ли он файл, как я видел его написанным несколько раз.

1 Ответ

1 голос
/ 16 апреля 2020

Повторная публикация моего комментария в качестве принятого ответа:

В основном это происходит: если объект файла, возвращенный open(), не имеет больше ссылок на него, файл будет закрыт. В этом случае словарь удерживает ссылку, но аналогично, когда не остается ссылок на словарь, он также удаляет ссылку на файл, когда он выходит из области видимости. Это может привести к ошибкам, когда дескрипторы файлов остаются открытыми. Python 3 предупредит об этом, если вы запустите с python -Wall. Для файлов, доступных только для чтения, это в основном безвредно, так как нет никаких данных, которые можно отправить на диск sh. Но я бы все равно этого избегал.

Например:

$ python3 -Wall
Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> {'f': open('.bashrc')}
{'f': <_io.TextIOWrapper name='.bashrc' mode='r' encoding='UTF-8'>}
>>> exit()
sys:1: ResourceWarning: unclosed file <_io.TextIOWrapper name='.bashrc' mode='r' encoding='UTF-8'>

На самом деле вам даже не нужен dict для этого:

$ python3 -Wall
Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> open('.bashrc')
<_io.TextIOWrapper name='.bashrc' mode='r' encoding='UTF-8'>
>>> exit()
sys:1: ResourceWarning: unclosed file <_io.TextIOWrapper name='.bashrc' mode='r' encoding='UTF-8'>

это потому что в последнем случае последнее возвращенное значение в REPL хранится в специальной переменной _.

Фактически, этот ResourceWarning будет вызываться каждый раз, когда файловый объект __del__ вызывается ранее он был явно закрыт:

$ python3 -Wall
Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> f = open('.bashrc')
>>> del f
__main__:1: ResourceWarning: unclosed file <_io.TextIOWrapper name='.bashrc' mode='r' encoding='UTF-8'>

Это всего лишь предупреждение (и по умолчанию отключено), поскольку это, как правило, не является серьезной проблемой, поскольку файл все равно будет закрыт. Но это может указывать на ошибку, но поэтому хорошо включить это предупреждение при отладке проблем ввода / вывода файлов, а также открывать файлы с помощью оператора with в качестве общей хорошей практики:

>>> with open(file_path, 'rb') as fobj:
...     body = { file_name: fobj }
...     # send request, etc...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...