Что-то делать перед выходом из программы

101

Как у вас может быть функция или что-то, что будет выполнено до выхода из вашей программы? У меня есть сценарий, который будет постоянно работать в фоновом режиме, и мне нужно, чтобы он сохранял некоторые данные в файл до его выхода. Есть стандартный способ сделать это?

Гоночный автомобиль
источник
2
Сценарий никогда не должен останавливаться, но, возможно, кто-то убьет процесс или нажмет Ctrl + \ или что-то в этом роде.
RacecaR 03

Ответы:

165

Ознакомьтесь с atexitмодулем:

http://docs.python.org/library/atexit.html

Например, если я хочу напечатать сообщение, когда мое приложение завершает работу:

import atexit

def exit_handler():
    print 'My application is ending!'

atexit.register(exit_handler)

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

Брент пишет код
источник
5
Есть ли способ сделать так, чтобы он был вызван при нажатии Ctrl + C или Ctrl + \?
RacecaR 03
8
Он будет вызван, если вы нажмете Ctrl + C. Это просто вызывает исключение KeyboardInterrupt.
Нед Батчелдер,
1
О, я забыл об этом. И я предполагаю, что ничего из того, что вы можете сделать, не запустится, если кто-то убьет процесс python, верно?
RacecaR 03
5
@RacecaR: действительно; суть убийства процесса в том, чтобы остановить его. Из документов: Note The exit function is not called when the program is killed by a signal, when a Python fatal internal error is detected, or when os._exit() is called.
Катриэль 03
18
@RacecaR, единственный способ запустить код завершения, даже если процесс сильно выйдет из строя или жестоко убит, - это другой процесс, известный как «монитор» или «сторожевой таймер», единственная задача которого - следить за целевым процессом и при необходимости введите код завершения. Конечно, это требует совсем другой архитектуры и имеет свои ограничения; если вам нужна такая функциональность, вам лучше открыть другой вопрос по этому вопросу.
Alex Martelli
32

Если вы хотите, чтобы что-то всегда работало, даже при ошибках, используйте try: finally:вот так -

def main():
    try:
        execute_app()
    finally:
        handle_cleanup()

if __name__=='__main__':
    main()

Если вы хотите также обрабатывать исключения, вы можете вставить except:передfinally:

Брайан С. Лейн
источник
14
Не работает при появлении SIGTERM из-за остановки процесса.
ramu
16

Если вы остановите сценарий, подняв a KeyboardInterrupt(например, нажав Ctrl-C), вы можете поймать это как стандартное исключение. Вы также можете поймать SystemExitтаким же образом.

try:
    ...
except KeyboardInterrupt:
    # clean up
    raise

Я упоминаю об этом только для того, чтобы вы знали об этом; «Правильный» способ сделать это - atexitмодуль, упомянутый выше.

Катриэль
источник