Страницы

Поиск по вопросам

понедельник, 1 октября 2018 г.

Завершение программы в Python

Как сделать раннее завершение программы в Python? В самоучителе я нашёл несколько примеров:
exit(0) sys.exit os.abort()
Однако там не было объяснения какой метод лучше. Какой метод является наиболее "безаварийным"?
И заодно: есть ли в Python понятие Autocloseable объектов? Если я сделаю ранее завершение программы, нужно ли мне будет закрывать файлы и т.д.?


Ответ

Короткий ответ: Лучше использовать sys.exit()

Механизм завершения процесса в Python реализован через бросание исключения SystemExit, таким образом можно просто создать подобное исключение и программа завершится:
raise SystemExit # или даже передать число -- код ошибки завершения программы raise SystemExit(1)
Функция exit и аналогичная ей quit созданы для удобства работы в интерактивном режиме и их не рекомендуется использовать внутри скриптов:
They are useful for the interactive interpreter shell and should not be used in programs.
По факту они также просто поднимают исключение, и при попытке вызова без скобок напишут подсказку о правильном способе выхода из интерпретатора:
>>> quit Use quit() or Ctrl-D (i.e. EOF) to exit >>> exit Use exit() or Ctrl-D (i.e. EOF) to exit
Использовать sys.exit стоит потому, что эта функция лежит в стандартном модуле и будет всегда там доступна. Также это довольно явный способ выразить своё желание завершить программу.
Есть также дополнительный метод для немедленного завершения программы: os._exit. У него довольно специфическая область применения, и там же есть замечание:
The standard way to exit is sys.exit(n)
Т.е. здесь даётся подтверждение того, что стандартный способ завершения программы -- это вызов sys.exit
Функция os.abort, упомянутая вами, использует механизм сигналов процессу. Конкретно при вызове этой функции будет передан сигнал SIGABRT, что в linux приведёт к завершению программы и созданию дампа памяти процесса. Подобное завершение рассматривается операционной системой как аварийное, поэтому не стоит использовать его для безаварийного завершения приложения.

По второй части вопроса. В Python есть развитая система контекстных менеджеров: классов, которые умеют работать с оператором with. Самое частое использование этого механизма встречается, вероятно, с файлами.
with open('filename') as my_file: print(my_file.read())
Этот код откроет файл, напечатает его содержимое на экран и закроет файл автоматически, даже если возникнет исключение при его печати.
Для классов, которые не приспособлены для работы с with есть функция closing в библиотеке contextlib. Из документации:
Code like this:
with closing(.open()) as f: is equivalent to this:
f = .open() try: finally: f.close()
Вот небольшой пример работы этой функции:
import contextlib
class Closeable: def close(self): print('closed')
with contextlib.closing(Closeable()): pass
# печатает closed

Теперь небольшое отступление о том, почему стоит использовать конструкцию with
Известно, что программа завершится от любого необработанного исключения, а не только от SystemExit. Таким образом, если в вашем коде используются какие-то ресурсы, которые требуется правильным образом закрывать перед завершением работы, нужно оборачивать работу с ними в блоки try ... finally ....
Однако, при использовании конструкции with это оборачивание происходит автоматически, и все ресурсы закрываются корректно.
Так как выход из программы -- это всего лишь брошенное исключение, то и в случае использования функции sys.exit закрытие открытых в операторе with ресурсов произойдёт корректно:
with contextlib.closing(Closeable()): sys.exit() # напечатает closed
Вы можете писать также и свои классы, предоставляющие ресурсы или классы, оборачивающие другие, которые нужно уметь закрывать автоматически. Для этого используются методы __enter__ и __exit__

Источники:
Похожий вопрос с англоязычного StackOverflow Функции, добавляемые модулем site Документация по конструкции with Документация по функции closing Документация по исключению SystemExit Документация по функции os._exit Документация по функции sys.exit Документация по функции os.abort Описание системного сигнала SIGABRT

Комментариев нет:

Отправить комментарий