Làm gì đó trước khi thoát chương trình


100

Làm thế nào bạn có thể có một chức năng hoặc một cái gì đó sẽ được thực thi trước khi chương trình của bạn thoát? Tôi có một tập lệnh sẽ liên tục chạy trong nền và tôi cần tập lệnh đó để lưu một số dữ liệu vào tệp trước khi thoát. Có một cách tiêu chuẩn để làm điều này?


2
Tập lệnh sẽ không bao giờ dừng lại, nhưng có thể ai đó sẽ giết quá trình hoặc nhấn Ctrl + \ hoặc thứ gì đó.
RacecaR

Câu trả lời:


165

Kiểm tra atexitmô-đun:

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

Ví dụ: nếu tôi muốn in một thông báo khi ứng dụng của tôi sắp kết thúc:

import atexit

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

atexit.register(exit_handler)

Chỉ cần lưu ý rằng điều này hoạt động tốt cho việc kết thúc tập lệnh bình thường, nhưng nó sẽ không được gọi trong mọi trường hợp (ví dụ: lỗi nội bộ nghiêm trọng).


5
Có cách nào để đặt nó ở nơi nó sẽ được gọi nếu bạn nhấn Ctrl + C hoặc Ctrl + \ không?
RacecaR

8
Nó sẽ được gọi nếu bạn nhấn Ctrl + C. Điều đó chỉ đơn giản là tăng một ngoại lệ KeyboardInterrupt.
Ned Batchelder

1
Ồ, tôi quên mất điều đó. Và tôi cho rằng không có gì bạn có thể làm sẽ được chạy nếu ai đó giết quá trình python phải không?
RacecaR

5
@RacecaR: thật vậy; điểm của việc giết chết một quy trình là ngăn chặn nó chết. Từ các tài liệu: 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.
Katriel

18
@RacecaR, cách duy nhất bạn có thể chạy mã kết thúc ngay cả khi một quy trình bị lỗi nghiêm trọng hoặc bị giết một cách dã man là trong một quy trình khác , được gọi là "giám sát" hoặc "cơ quan giám sát", công việc duy nhất của họ là theo dõi quy trình mục tiêu và chạy mã kết thúc khi thích hợp. Tất nhiên điều đó đòi hỏi một kiến ​​trúc rất khác và có những hạn chế của nó; nếu bạn cần chức năng như vậy, tốt nhất bạn nên mở một Q khác về vấn đề này.
Alex Martelli

32

Nếu bạn muốn thứ gì đó luôn chạy, ngay cả khi có lỗi, hãy sử dụng try: finally:như thế này -

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

if __name__=='__main__':
    main()

Nếu bạn cũng muốn xử lý các ngoại lệ, bạn có thể chèn một except:trướcfinally:


13
Không hoạt động khi SIGTERM xảy ra do quá trình bị giết.
ramu

16

Nếu bạn dừng tập lệnh bằng cách tăng một KeyboardInterrupt(ví dụ: bằng cách nhấn Ctrl-C), bạn có thể coi đó chỉ là một ngoại lệ tiêu chuẩn. Bạn cũng có thể bắt SystemExittheo cách tương tự.

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

Tôi đề cập điều này chỉ để bạn biết về nó; cách 'đúng đắn' để làm điều này là atexitmô-đun được đề cập ở trên.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.