Подтвердить что ты не робот

Закрываются ли файлы во время выхода из исключения?

Открываются ли открытые файлы (и другие ресурсы) при закрытии script из-за исключения?

Мне интересно, нужно ли закрывать мои ресурсы во время обработки исключений.

** EDIT: более конкретно, я создаю простой файл журнала в своем script. Я хочу знать, должен ли я быть обеспокоен закрытием файла журнала явно в случае исключений. поскольку мой script имеет сложные, вложенные, try/except блоки, делает это несколько сложнее, поэтому, если python, CLIB или ОС закрывают мой текстовый файл, когда script выходит из строя/ошибки, я не делаю Не хотите тратить слишком много времени на то, чтобы убедиться, что файл закрыт.

Если в руководстве Python есть часть, в которой говорится об этом, обратитесь к нему, но я не смог его найти.

4b9b3361

Ответ 1

Нет, они этого не делают.

Используйте оператор with, если вы хотите, чтобы ваши файлы были закрыты, даже если произошло исключение.

Из docs:

Оператор with используется для обертывания выполнения блока с помощью методы, определенные менеджером контекста. Это позволяет попробуйте... кроме... наконец шаблоны использования, которые будут инкапсулированы для удобного повторного использования.

Из docs:

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

with open("myfile.txt") as f:
    for line in f:
        print line,

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

Ответ 2

Довольно простой вопрос.

Два ответа.

Одна поговорка "Да".

Другое высказывание: "Нет!"

Оба со значительными upvotes.

Кому верить? Позвольте мне попытаться пояснить.


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

Сначала рассмотрим, что подразумевается под закрытием файла из операционных систем перспектива.

Когда процесс завершается, операционная система очищает все ресурсы что только этот процесс был открыт. В противном случае плохо управляемые программы, которые аварии, но не освободили их ресурсы, могли бы потреблять всю систему ресурсы.

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

Теперь, как насчет закрытия файлов с точки зрения Pythons? Если какая-либо программа записанные на любом выходе из языка программирования, большинство ресурсов будет очищено но как Python обрабатывает очистку внутри стандартных программ Python?

Стандартная реализация CPython для Python - в отличие от другого Python реализации, такие как Jython, использует подсчет ссылок для выполнения большинства своих вывоз мусора. Объект имеет поле отсчета ссылок. Каждый раз что-то в Python получает ссылку на какой-то другой объект, ссылка Поле count в указанном объекте увеличивается. Когда ссылка потеря, например, поскольку переменная больше не находится в области видимости, счетчик ссылок убавления. Когда счетчик ссылок достигает нуля, код Python не может достигнуть объект больше, поэтому объект освобождается. И когда он получает deallocated, Python вызывает деструктор __del__().

Метод Pythons __del__() для файлов сбрасывает буферы и закрывает файл с точки зрения операционных систем. Из-за ссылки подсчет, в CPython, если вы открываете файл в функции и не возвращаете file, тогда счетчик ссылок на файл опускается до нуля, когда функция завершается, и файл автоматически размывается и закрывается. когда программа заканчивается, CPython разделяет все объекты, и все объекты имеют их деструкторы называются, даже если программа заканчивается из-за неполученного исключение. (Это технически не подходит для патологического случая, когда у вас есть цикл объектов с деструкторами, по крайней мере, в версиях Python до 3.4.)

Но это просто реализация CPython. Язык Python определен в ссылке на языке Python, что и есть все Python реализации должны следовать, чтобы называть себя Python-совместимый.

Справочник по языку объясняет управление ресурсами в модели данных раздел:

Некоторые объекты содержат ссылки на "внешние" ресурсы, такие как открытые файлов или окон. Понятно, что эти ресурсы освобождаются, когда объект собран с мусором, но поскольку сбор мусора не гарантировано, что такие объекты также предоставляют явный освободить внешний ресурс, обычно метод close(). Программы настоятельно рекомендуется явно закрыть такие объекты. "Try... finally" и оператор "with" обеспечивают удобство способы сделать это.

То есть CPython, как правило, сразу же закрывает объект, но может изменение в будущей версии и другие реализации Python arent даже требуется для закрытия объекта вообще.

Итак, для переносимости и потому что явный лучше, чем неявный, его настоятельно рекомендуется называть close() всем, что может быть close() d, и сделать это в блоке finally, если есть код между создание объекта и close(), которые могут вызвать исключение. Или использовать синтаксический сахар with, который выполняет одно и то же. Если вы это сделаете то, тогда буферы на файлах будут сброшены, даже если исключение будет поднят.

Однако даже при выполнении инструкции with одни и те же основные механизмы на работе. Если программа вылетает так, что не дает Pythons __del__() метод запуска, вы все равно можете получить коррумпированный файл на диске:

#!/usr/bin/env python3.3

import ctypes

# Cast the memory adress 0x0001 to the C function int f()
prototype = ctypes.CFUNCTYPE(int)
f = prototype(1)

with open('foo.txt', 'w'):
    x.write('hi')
    # Segfault
    print(f())

Эта программа создает файл нулевой длины. Это ненормальный случай, но он показывает, что даже с ресурсами with обязательно очистите то, что вы ожидаете. Python рассказывает о систему, чтобы открыть файл для записи, который создает его на диске; Python пишет hi в буферы C библиотеки stdio; и затем он падает до with утверждение заканчивается, и из-за очевидного повреждения памяти, его небезопасно чтобы операционная система попыталась прочитать остатки буфера и вывести их на диск. Таким образом, программа не может правильно очиститься, даже если оператор a with. Упс. Несмотря на это, close() и with почти всегда работают, и ваша программа всегда лучше иметь их, чем не иметь их.

Таким образом, ответ не будет ни да, ни нет. Оператор with и close() технически не являются необходимых для большинства обычных программ CPython. Но не используя их результаты не переносимый код, который будет выглядеть неправильно. И хотя они чрезвычайно полезно, они все же могут потерпеть неудачу в патологических случаях.

Ответ 3

Да, да.

Это CLIB (по крайней мере, в cpython) и предмет операционной системы. Когда script завершает работу, CLIB будет скрывать и закрывать все объекты файлов. Даже если это не так (например, сам python падает), операционная система закрывает свои ресурсы так же, как и любой другой процесс. Неважно, было ли это исключение или нормальный выход или даже его питон или любая другая программа.

Здесь script, который записывает файл и создает исключение, прежде чем содержимое файла будет сброшено на диск. Прекрасно работает:

~/tmp/so$ cat xyz.txt
cat: xyz.txt: No such file or directory
~/tmp/so$ cat exits.py
f = open("xyz.txt", "w")
f.write("hello")
print("file is", open("xyz.txt").read())
assert False

~/tmp/so$ python exits.py
('file is', '')
Traceback (most recent call last):
  File "exits.py", line 4, in <module>
    assert False
AssertionError
~/tmp/so$ cat xyz.txt
hello

Ответ 4

У меня, как и другие люди в этой теме, остается вопрос: "Ну что же, наконец, правда?"

Теперь предположим, что файлы остаются открытыми при преждевременном завершении программы - и есть много таких случаев помимо исключений из-за обработки файлов - единственный безопасный способ избежать этого - читать все (или часть файла) в буфер и закрыть его. Затем обрабатывайте содержимое в буфере по мере необходимости. Это особенно. случай для глобального поиска, изменений и т.д., которые должны быть сделаны в файле. После того, как изменения будут выполнены, можно сразу же записать весь буфер в тот же или другой файл, избегая риска оставить открытый файл открытым - делая много чтений и писем, что является наихудшим случаем всех