Имеет ли смысл обработчик исключений приложений?
Короче говоря, у меня есть существенное приложение Python, которое, среди прочего, выделяет "losetup", "mount" и т.д. в Linux. По существу потребляющие системные ресурсы, которые должны быть выпущены по завершении.
Если мое приложение выйдет из строя, я хочу, чтобы эти системные ресурсы были правильно выпущены.
Имеет ли смысл делать что-то вроде следующего?
def main():
# TODO: main application entry point
pass
def cleanup():
# TODO: release system resources here
pass
if __name__ == "__main__":
try:
main()
except:
cleanup()
raise
Это что-то, что обычно делается? Есть ли способ лучше? Возможно, деструктор в одноэлементном классе?
Ответы
Ответ 1
Мне нравятся обработчики исключений верхнего уровня в целом (независимо от языка). Это отличное место для очистки ресурсов, которые не могут быть немедленно связаны с ресурсами, потребляемыми внутри метода, который генерирует исключение.
Это также фантастическое место для log тех исключений, если у вас такая структура. Обработчики верхнего уровня поймут те странные исключения, которые вы не планировали, и дайте им возможность исправить их в будущем, иначе вы никогда не узнаете о них вообще.
Просто будьте осторожны, чтобы ваш обработчик верхнего уровня не генерировал исключений!
Ответ 2
Деструктор (как в методе __del__) - плохая идея, поскольку они не гарантируются. Модуль atexit является более безопасным, хотя они все равно не срабатывают, если сработает интерпретатор Python (а не приложение Python) или используется os._exit(), или процесс будет убит агрессивно или перезагрузка компьютера. (Конечно, последний элемент не является проблемой в вашем случае.) Если ваш процесс подвержен ошибкам (например, он использует неподходящие сторонние модули расширения), вы можете выполнить очистку в простом родительском процессе для больше изоляции.
Если вы не очень обеспокоены, используйте модуль atexit.
Ответ 3
Применение широкого обработчика в порядке. Они отлично подходят для ведения журнала. Просто убедитесь, что приложение широкое, оно долговечно и вряд ли врежется самому себе.
Ответ 4
если вы используете классы, вы должны освобождать ресурсы, которые они выделяют в своих деструкторах, но, конечно. Используйте try: для всего приложения, только если вы хотите освободить ресурсы, которые еще не освобождены деструкторами ваших классов.
И вместо использования catch-all except:, вы должны использовать следующий блок:
try:
main()
finally:
cleanup()
Это обеспечит очистку более питоническим способом.
Ответ 5
Это похоже на разумный подход и более простой и надежный, чем деструктор в одноэлементном классе. Вы также можете посмотреть на модуль atexit. (Выражение "at exit", а не "tex it" или что-то в этом роде. Я немного смутил это.)
Ответ 6
Рассмотрите возможность записи диспетчера контекстов и использования инструкции with.