Ich mache unterwegs ein Verzeichnis, aber ich möchte nicht, dass es am Ende bleibt. Ich habe temporäre Daten in die Datenbank eingefügt, möchte aber nicht, dass sie am Ende verbleiben. Bitte lassen Sie mich wissen, wenn das Programm beendet ist, ob es normal oder tot ist.
Dies ist ein Weg, um dies zu erreichen.
Dieses Mal werde ich die folgenden Dinge anstreben.
Ich werde verschiedene Methoden ausprobieren. Für diejenigen, die es eilig haben, werde ich zuerst die Schlussfolgerung schreiben.
import sys
import time
import signal
def setup():
print("!!!Set up!!!")
def cleanup():
print("!!!Clean up!!!")
#Bereinigungsverarbeitung verschiedene
time.sleep(10)
print("!!!Clean up Done!!!")
def sig_handler(signum, frame) -> None:
sys.exit(1)
def main():
setup()
signal.signal(signal.SIGTERM, sig_handler)
try:
#Verschiedene Verarbeitung
time.sleep(60)
finally:
signal.signal(signal.SIGTERM, signal.SIG_IGN)
signal.signal(signal.SIGINT, signal.SIG_IGN)
cleanup()
signal.signal(signal.SIGTERM, signal.SIG_DFL)
signal.signal(signal.SIGINT, signal.SIG_DFL)
if __name__ == "__main__":
sys.exit(main())
Bereiten Sie die Funktion setup ()
/ clean ()
und den Hauptteil vor.
def setup():
print("!!!Set up!!!")
def cleanup():
print("!!!Clean up!!!")
def main():
pass
if __name__ == "__main__":
sys.exit(main())
Das erste, was mir in den Sinn kommt, ist try --finally zu verwenden.
def main():
setup()
try:
print("Do some jobs")
finally:
cleanup()
Lass es uns laufen.
!!!set up!!!
do some jobs
!!!Clean up!!!
Es wurde aufgeräumt. Was aber, wenn unterwegs ein Fehler auftritt?
def main():
setup()
try:
print(1 / 0)
finally:
cleanup()
Ich werde es versuchen.
!!!set up!!!
!!!Clean up!!!
Traceback (most recent call last):
File "./try-finally.py", line 26, in <module>
sys.exit(main())
File "./try-finally.py", line 19, in main
print(1 / 0)
ZeroDivisionError: division by zero
Dies wurde auch aufgeräumt.
Aber was ist, wenn Sie mit Strg-C aufhören?
def main():
setup()
try:
time.sleep(60)
finally:
cleanup()
Führen Sie es aus und drücken Sie Strg-C in der Mitte, um es zu stoppen.
!!!Set up!!!
^C!!!Clean up!!!
Traceback (most recent call last):
File "./try-finally.py", line 27, in <module>
sys.exit(main())
File "./try-finally.py", line 20, in main
time.sleep(60)
KeyboardInterrupt
Anscheinend hat es funktioniert.
Aber was ist, wenn Sie mit töten getötet haben?
!!!Set up!!!
Terminated
Dies sollte nicht getan werden. Dies hinterlässt eine Mülldatei.
versuche es - endlich
Python hat ein Atexit, das es beim Beenden ausführt. Lass uns das versuchen.
def main():
setup()
atexit.register(cleanup)
print("Do some jobs")
Lass es uns laufen.
!!!Set up!!!
Do some jobs
!!!Clean up!!!
Es ging gut. Als nächstes erhalten wir einen Fehler.
def main():
setup()
atexit.register(cleanup)
print(1 / 0)
Ich werde es versuchen.
!!!Set up!!!
Traceback (most recent call last):
File "./try-finally.py", line 25, in <module>
sys.exit(main())
File "./try-finally.py", line 21, in main
print(1 / 0)
ZeroDivisionError: division by zero
!!!Clean up!!!
Das hat auch funktioniert. Im Vergleich zu --finally ist der Bereinigungsprozess später.
Was ist, wenn Sie mit Strg-C aufhören?
def main():
setup()
atexit.register(cleanup)
time.sleep(60)
Führen Sie es aus und versuchen Sie es mit Strg-C in der Mitte zu stoppen.
!!!Set up!!!
^CTraceback (most recent call last):
File "./try-finally.py", line 25, in <module>
sys.exit(main())
File "./try-finally.py", line 21, in main
time.sleep(60)
KeyboardInterrupt
!!!Clean up!!!
wohlfühlen.
Dann hören wir endlich mit dem Töten auf.
!!!Set up!!!
Terminated
Es tut uns leid. Wie try-finally scheint es auch nicht zu funktionieren.
in atexit
Der Befehl kill sendet ein Signal namens SIGTERM an den Prozess. Strg-C sendet auch ein Signal namens SIGINT an den Prozess. Versuchen wir, diese Signale einzufangen.
def sig_handler(signum, frame) -> None:
cleanup()
sys.exit(1)
def main():
setup()
signal.signal(signal.SIGTERM, sig_handler)
signal.signal(signal.SIGINT, sig_handler)
print("Do some jobs")
Ich werde es versuchen.
!!!Set up!!!
Do some jobs
Eine Bereinigung wird nicht durchgeführt. Das liegt daran, dass das Signal nicht von außen geflogen ist. Es ist natürlich. Da die Ausnahme dieselbe ist, wird die Bestätigung weggelassen.
Nun wollen wir sehen, was mit Strg-C passiert.
def main():
setup()
signal.signal(signal.SIGTERM, sig_handler)
signal.signal(signal.SIGINT, sig_handler)
time.sleep(60)
Führen Sie es aus und versuchen Sie es mit Strg-C in der Mitte zu stoppen.
!!!Set up!!!
^C!!!Clean up!!!
Es ist perfekt. Die KeyboardInterrupt-Ausnahme ist verschwunden, sollte aber normalerweise kein Problem sein. Falls unbedingt erforderlich, können Sie (KeyboardInterrupt ()) in sig_handler erhöhen.
Dann ist es ein Mord, um den man sich Sorgen machen muss, aber was wird passieren?
!!!Set up!!!
!!!Clean up!!!
Toll! Es wurde mit einem Kitin aufgeräumt.
Versuchen Sie also --finally oder atexit und signal sollten kombiniert werden.
Dieses Mal werde ich unter der Annahme, dass der Umfang eng ist, versuchen, try - final und signal zu kombinieren.
def sig_handler(signum, frame) -> None:
cleanup()
sys.exit(1)
def main():
setup()
signal.signal(signal.SIGTERM, sig_handler)
try:
print("do some jobs")
finally:
signal.signal(signal.SIGTERM, signal.SIG_DFL)
cleanup()
Es wurde so. Strg-C funktioniert auch mit try --finally, also habe ich nur SIGTERM gefangen. Nach dem Beenden des Versuchs sollte keine Bereinigung erforderlich sein. Setzen Sie SIGTERM schließlich auf den Standardwert zurück.
Lass es uns laufen.
!!!Set up!!!
do some jobs
!!!Clean up!!!
Wie erwartet.
Als nächstes erhalten wir einen Fehler.
def main():
setup()
signal.signal(signal.SIGTERM, sig_handler)
try:
print(1 / 0)
finally:
signal.signal(signal.SIGTERM, signal.SIG_DFL)
cleanup()
if __name__ == "__main__":
sys.exit(main())
Ich werde es versuchen.
!!!Set up!!!
!!!Clean up!!!
Traceback (most recent call last):
File "./try-finally.py", line 33, in <module>
sys.exit(main())
File "./try-finally.py", line 26, in main
print(1 / 0)
ZeroDivisionError: division by zero
Es wurde aufgeräumt.
Aktivieren Sie als Nächstes Strg-C.
def main():
setup()
signal.signal(signal.SIGTERM, sig_handler)
try:
time.sleep(60)
finally:
signal.signal(signal.SIGTERM, signal.SIG_DFL)
cleanup()
Führen Sie es aus und drücken Sie Strg-C in der Mitte.
!!!Set up!!!
^CClean up!!
Traceback (most recent call last):
File "./try-finally.py", line 33, in <module>
sys.exit(main())
File "./try-finally.py", line 26, in main
time.sleep(60)
KeyboardInterrupt
Dies wurde auch aufgeräumt.
Was ist nun mit töten?
!!!Set up!!!
!!!Clean up!!!
!!!Clean up!!!
eh! Es wurde zweimal aufgeräumt.
Durch das Einfangen von SIGTERM scheint Python nicht endgültig getötet und ausgeführt worden zu sein. Ändern wir also sig_handler wie folgt.
def sig_handler(signum, frame) -> None:
sys.exit(1)
Ich habe aufgehört, die Bereinigung im Handler aufzurufen, und habe sie gerade beendet.
Führen Sie es aus und versuchen Sie es zu töten.
!!!Set up!!!
!!!Clean up!!!
Es ist endlich wie erwartet.
Die vorherige Methode ist ausreichend, aber es liegt in der Natur des Menschen, Strg-C wiederholt zu drücken, wenn Sie nicht sofort nach dem Drücken von Strg-C anhalten. Sie können kill auch viele Male ausführen.
Ich habe den Bereinigungsprozess zum Laufen gebracht, aber das ist ein Chaos. Also werde ich es während der Bereinigung nicht stoppen.
def main():
setup()
signal.signal(signal.SIGTERM, sig_handler)
try:
time.sleep(60)
finally:
signal.signal(signal.SIGTERM, signal.SIG_IGN)
signal.signal(signal.SIGINT, signal.SIG_IGN)
cleanup()
signal.signal(signal.SIGTERM, signal.SIG_DFL)
signal.signal(signal.SIGINT, signal.SIG_DFL)
Ignorieren Sie Strg-C und beenden Sie die Signale vor der Bereinigung (). Stellen Sie nach cleanup () die Standardeinstellung wieder her. Dies ist perfekt.
Betrachtet man diesmal die Ergebnisse, so scheint der einzige Unterschied zwischen Try-Catch und Atexit der Unterschied in Umfang und Zeitpunkt zu sein. Wenn das Setup in der Mitte eines Programms ausgeführt wird, verwenden Sie try --finally in diesem Bereich. Wenn Setup das erste ist, was Sie in Ihrem Programm ausführen, verwenden Sie atexit. Wenn Sie möchten, dass es am Ende jederzeit ausgeführt wird, unabhängig vom Setup, verwenden Sie atexit. Bedeutet das?
Es gibt auch eine Möglichkeit, mit zu verwenden. Wenn Sie also interessiert sind, versuchen Sie es bitte.
Recommended Posts