Melakukan sesuatu sebelum keluar dari program

100

Bagaimana Anda bisa memiliki fungsi atau sesuatu yang akan dieksekusi sebelum program Anda berhenti? Saya memiliki skrip yang akan terus berjalan di latar belakang, dan saya membutuhkannya untuk menyimpan beberapa data ke file sebelum keluar. Apakah ada cara standar untuk melakukan ini?

Mobil balap
sumber
2
Skrip tidak boleh berhenti, tapi mungkin seseorang akan menghentikan proses atau menekan Ctrl + \ atau sesuatu.
RacecaR

Jawaban:

165

Lihat atexitmodulnya:

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

Misalnya, jika saya ingin mencetak pesan ketika aplikasi saya dihentikan:

import atexit

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

atexit.register(exit_handler)

Perlu diketahui bahwa ini berfungsi dengan baik untuk penghentian normal skrip, tetapi tidak akan dipanggil di semua kasus (mis. Kesalahan internal yang fatal).

Brent Menulis Kode
sumber
5
Apakah ada cara untuk membuatnya di tempat yang akan dipanggil jika Anda menekan Ctrl + C atau Ctrl + \?
RacecaR
8
Ini akan dipanggil jika Anda menekan Ctrl + C. Itu hanya menimbulkan pengecualian KeyboardInterrupt.
Ned Batchelder
1
Oh, saya lupa itu. Dan saya berasumsi bahwa tidak ada yang dapat Anda lakukan yang akan dijalankan jika seseorang membunuh proses python, bukan?
RacecaR
5
@RacecaR: memang; tujuan membunuh suatu proses adalah menghentikannya mati. Dari docs: 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, satu-satunya cara Anda dapat menjalankan kode penghentian bahkan jika proses crash parah atau terbunuh secara brutal adalah dalam proses lain , yang dikenal sebagai "monitor" atau "pengawas", yang tugas satu-satunya adalah mengawasi proses target dan jalankan kode terminasi jika sesuai. Tentu saja hal itu membutuhkan arsitektur yang sangat berbeda dan memiliki keterbatasan; jika Anda membutuhkan fungsionalitas seperti itu, sebaiknya Anda membuka Q yang berbeda tentang masalah tersebut.
Alex Martelli
32

Jika Anda ingin sesuatu selalu berjalan, bahkan pada kesalahan, gunakan try: finally:seperti ini -

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

if __name__=='__main__':
    main()

Jika Anda juga ingin menangani pengecualian, Anda dapat menyisipkan except:sebelumfinally:

Brian C. Lane
sumber
13
Tidak berfungsi saat SIGTERM terjadi karena proses mati.
ramu
16

Jika Anda menghentikan skrip dengan menaikkan a KeyboardInterrupt(misalnya dengan menekan Ctrl-C), Anda dapat menangkapnya hanya sebagai pengecualian standar. Anda juga bisa menangkap SystemExitdengan cara yang sama.

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

Saya menyebutkan ini hanya agar Anda mengetahuinya; cara yang 'tepat' untuk melakukannya adalah dengan atexitmodul yang disebutkan di atas.

Katriel
sumber