ทำบางอย่างก่อนออกจากโปรแกรม


102

คุณจะมีฟังก์ชันหรือบางสิ่งที่จะดำเนินการก่อนที่โปรแกรมของคุณจะหยุดทำงานได้อย่างไร? ฉันมีสคริปต์ที่จะทำงานอยู่เบื้องหลังตลอดเวลาและฉันต้องการให้มันบันทึกข้อมูลบางส่วนลงในไฟล์ก่อนที่จะออก มีวิธีมาตรฐานในการทำเช่นนี้หรือไม่?


2
สคริปต์ไม่ควรหยุด แต่อาจมีคนฆ่ากระบวนการหรือกด Ctrl + \ หรืออะไรบางอย่าง
RacecaR

คำตอบ:


167

ตรวจสอบatexitโมดูล:

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

ตัวอย่างเช่นหากฉันต้องการพิมพ์ข้อความเมื่อแอปพลิเคชันของฉันกำลังยุติ:

import atexit

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

atexit.register(exit_handler)

โปรดทราบว่าสิ่งนี้ใช้ได้ดีสำหรับการยุติสคริปต์ตามปกติ แต่จะไม่ถูกเรียกในทุกกรณี (เช่นข้อผิดพลาดภายในที่ร้ายแรง)


6
มีวิธีใดบ้างที่จะทำให้มันถูกเรียกใช้ถ้าคุณกด 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.
Katriel

18
@RacecaR วิธีเดียวที่คุณสามารถเรียกใช้รหัสการยุติแม้ว่ากระบวนการจะขัดข้องอย่างรุนแรงหรือถูกฆ่าอย่างไร้ความปราณีอยู่ในกระบวนการอื่นที่เรียกว่า "มอนิเตอร์" หรือ "สุนัขเฝ้าบ้าน" ซึ่งมีหน้าที่เพียงอย่างเดียวคือคอยจับตาดูกระบวนการเป้าหมายและ เรียกใช้รหัสการยกเลิกเมื่อเหมาะสม แน่นอนว่าต้องใช้สถาปัตยกรรมที่แตกต่างกันมากและมีข้อ จำกัด หากคุณต้องการฟังก์ชันดังกล่าวคุณควรเปิด Q อื่นในเรื่องนี้
Alex Martelli

32

หากคุณต้องการให้บางสิ่งทำงานอยู่เสมอแม้จะเกิดข้อผิดพลาดให้ใช้try: finally:สิ่งนี้

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

if __name__=='__main__':
    main()

หากคุณต้องการจัดการข้อยกเว้นคุณสามารถแทรกexcept:ก่อนหน้าไฟล์finally:


14
ไม่ทำงานเมื่อ SIGTERM เกิดขึ้นเนื่องจากการฆ่ากระบวนการ
ramu

16

หากคุณหยุดสคริปต์โดยเพิ่มKeyboardInterrupt(เช่นโดยการกด Ctrl-C) คุณสามารถจับได้ว่าเป็นข้อยกเว้นมาตรฐาน คุณยังสามารถจับSystemExitในลักษณะเดียวกัน

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

ฉันพูดถึงสิ่งนี้เพื่อให้คุณรู้เกี่ยวกับเรื่องนี้ วิธีที่ 'ถูกต้อง' คือatexitโมดูลที่กล่าวถึงข้างต้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.