Робити щось перед виходом із програми


100

Як ви можете мати функцію або щось, що буде виконано до виходу вашої програми? У мене є сценарій, який буде постійно працювати у фоновому режимі, і мені він потрібен, щоб зберегти деякі дані до файлу до його виходу. Чи існує стандартний спосіб зробити це?


2
Сценарій ніколи не повинен зупинятися, але, можливо, хтось вб’є процес або натисне Ctrl + \ або щось інше.
RacecaR

Відповіді:


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

8
Він буде викликаний, якщо натиснути Ctrl + C. Це просто викликає виняток KeyboardInterrupt.
Ned Batchelder

1
О, я це забув. І я припускаю, що нічого, що ви можете зробити, не буде запущено, якщо хтось вб’є процес python, чи не так?
RacecaR

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.
Катріель

18
@RacecaR, єдиний спосіб, яким ви можете запустити код завершення, навіть якщо процес погано збивається або жорстоко вбивається, - це інший процес, відомий як "монітор" або "сторожовий собака", єдиною роботою якого є стеження за цільовим процесом і запустити код припинення, коли це доречно. Звичайно, це вимагає зовсім іншої архітектури і має свої обмеження; якщо вам потрібна така функціональність, вам найкраще відкрити інший Q з цього питання.
Alex Martelli,

32

Якщо ви хочете, щоб щось завжди працювало, навіть з помилками, використовуйте try: finally:так -

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

if __name__=='__main__':
    main()

Якщо ви хочете також обробляти винятки, ви можете вставити except:передfinally:


13
Не працює, коли SIGTERM відбувається через вбивство процесу.
ramu

16

Якщо ви зупините сценарій, піднявши a KeyboardInterrupt(наприклад, натиснувши Ctrl-C), ви зможете зрозуміти це як стандартний виняток. Ви також можете ловити SystemExitтаким же чином.

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

Я згадую це лише для того, щоб ви про це знали; «правильним» способом зробити це є atexitзгаданий вище модуль.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.