Имеет ли смысл обработчик исключений приложений?

Короче говоря, у меня есть существенное приложение 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.