Ich möchte am Ende etwas mit Python machen

Ich möchte am Ende etwas mit Python machen

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.

  1. Natürlich möchte ich, dass du es tust, wenn es normal ist
  2. Ich möchte, dass Sie ausgeführt werden, auch wenn eine Ausnahme auftritt
  3. Ich möchte, dass Sie ausgeführt werden, auch wenn Sie mit Strg-C aufhören
  4. Ich möchte, dass Sie ausgeführt werden, auch wenn Sie mit dem Töten aufhören
  5. Stoppen Sie nicht während des Bereinigungsvorgangs
  6. Gib Kill -9 und Segmentaion Fault auf

Ich werde verschiedene Methoden ausprobieren. Für diejenigen, die es eilig haben, werde ich zuerst die Schlussfolgerung schreiben.

Fazit zuerst

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())

Kommentar

Vorbereitung

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())

benutze try --finally

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.

Fazit

versuche es - endlich

  1. Natürlich möchte ich, dass Sie es tun, wenn es normal ist ⇨ ○
  2. Ich möchte, dass Sie auch dann ausgeführt werden, wenn eine Ausnahme auftritt ⇨ ○
  3. Ich möchte, dass Sie ausgeführt werden, auch wenn Sie mit Strg-C ⇨ ○ aufhören
  4. Ich möchte, dass Sie ausgeführt werden, auch wenn Sie mit kill ⇨ × aufhören

benutze atexit

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.

Fazit

in atexit

  1. Natürlich möchte ich, dass Sie es tun, wenn es normal ist ⇨ ○
  2. Ich möchte, dass Sie auch dann ausgeführt werden, wenn eine Ausnahme auftritt ⇨ ○
  3. Ich möchte, dass Sie ausgeführt werden, auch wenn Sie mit Strg-C ⇨ ○ aufhören
  4. Ich möchte, dass Sie ausgeführt werden, auch wenn Sie mit kill ⇨ × aufhören

Signal verwenden

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.

Fazit

  1. Natürlich möchte ich, dass du es machst, wenn es normal ist ⇨ ×
  2. Ich möchte, dass Sie ausgeführt werden, auch wenn eine Ausnahme auftritt ⇨ ×
  3. Ich möchte, dass Sie ausgeführt werden, auch wenn Sie mit Strg-C ⇨ ○ aufhören
  4. Ich möchte, dass Sie ausgeführt werden, auch wenn Sie mit kill ⇨ ○ aufhören

Versuchen Sie also --finally oder atexit und signal sollten kombiniert werden.

Verwenden Sie try - endlich in Kombination mit dem Signal

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.

Fazit

  1. Natürlich möchte ich, dass Sie es tun, wenn es normal ist ⇨ ○
  2. Ich möchte, dass Sie auch dann ausgeführt werden, wenn eine Ausnahme auftritt ⇨ ○
  3. Ich möchte, dass Sie ausgeführt werden, auch wenn Sie mit Strg-C ⇨ ○ aufhören
  4. Ich möchte, dass Sie ausgeführt werden, auch wenn Sie mit kill ⇨ ○ aufhören

Stoppen Sie nicht während des Bereinigungsvorgangs

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.

Fazit

  1. Natürlich möchte ich, dass Sie es tun, wenn es normal ist ⇨ ○
  2. Ich möchte, dass Sie auch dann ausgeführt werden, wenn eine Ausnahme auftritt ⇨ ○
  3. Ich möchte, dass Sie ausgeführt werden, auch wenn Sie mit Strg-C ⇨ ○ aufhören
  4. Ich möchte, dass Sie ausgeführt werden, auch wenn Sie mit kill ⇨ ○ aufhören
  5. Halten Sie nicht mitten im Beendigungsprozess an ⇨ ○

Bonus

Verwenden Sie try --finally / atexit richtig

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

Ich möchte am Ende etwas mit Python machen
Ich möchte so etwas wie Uniq in Python sortieren
Ich wollte so etwas wie Elixirs Pipe in Python machen
Ich möchte mit Python ein Fenster erstellen
Ich möchte verschachtelte Dicts in Python zusammenführen
Ich möchte den Fortschritt in Python anzeigen!
Ich möchte Affenpatches nur teilweise sicher mit Python machen
Ich möchte in Python schreiben! (1) Überprüfung des Codeformats
Ich möchte eine Variable in einen Python-String einbetten
Ich möchte Timeout einfach in Python implementieren
Ich möchte in Python schreiben! (2) Schreiben wir einen Test
Auch mit JavaScript möchte ich Python `range ()` sehen!
Ich möchte eine Datei mit Python zufällig testen
Ich möchte mit einem Roboter in Python arbeiten.
Ich möchte in Python schreiben! (3) Verwenden Sie Mock
Ich möchte Strings in Kotlin wie Python manipulieren!
Ich möchte die Effizienz mit Python auch in einem experimentellen System verbessern. (3) Ich möchte mit Pandas so etwas wie Excel machen
[Python] Wie man PCA mit Python macht
Ich möchte ○○ mit Pandas machen
Ich möchte mit Python debuggen
Was tun, wenn in Python "SSL: CERTIFICATE_VERIFY_FAILED _ssl.c: 1056" angezeigt wird?
Ich möchte eine schöne Ergänzung zu input () in Python hinzufügen
[Unterprozess] Wenn Sie ein anderes Python-Programm in Python-Code ausführen möchten
Ich habe versucht, Permutation in Python zu implementieren
Ich möchte in der Einschlussnotation drucken
So machen Sie R chartr () in Python
Ich möchte APG4b mit Python lösen (nur 4.01 und 4.04 in Kapitel 4)
Ich habe versucht, PLSA in Python 2 zu implementieren
Ich möchte eine Python-Umgebung erstellen
Ich möchte Python GUI ausführen, wenn Raspberry Pi startet
Ich möchte den vollständigen Text mit elasticsearch + python durchsuchen
[Python] Wenn Sie alle Variablen in einer anderen Datei verwenden möchten
Ich möchte Protokolle mit Python analysieren
Ich möchte mit aws mit Python spielen
[Python / AWS Lambda-Ebenen] Ich möchte nur Module in AWS Lambda-Ebenen wiederverwenden
Ich habe versucht, ADALINE in Python zu implementieren
Ich wollte ABC159 mit Python lösen
Ich möchte Matplotlib in PySimpleGUI einbetten
Was tun, wenn ModuleNotFoundError: In Python tritt kein Modul mit dem Namen 'XXX' auf
Eine Geschichte, die ich machen wollte, als ich eine Liste von Lernsitzungen mit Python bekam
Was tun, wenn der Werttyp in Python nicht eindeutig ist?
Ich möchte es mit Python Lambda Django machen, aber ich werde aufhören
Ich möchte eine in Python in PDF konvertierte Tabelle wieder in CSV konvertieren
Ich möchte das Ergebnis von "Zeichenfolge" .split () in Python stapelweise konvertieren
Ich möchte die abstrakte Klasse (ABCmeta) von Python im Detail erklären
Ich möchte einen Teil der Excel-Zeichenfolge mit Python einfärben
Was soll ich verwenden, um Typvergleiche in Python durchzuführen?
Ich möchte MATLAB feval mit Python verwenden
Ich möchte Datetime.now in Djangos Test reparieren
Ich möchte mich mit Schlüsselwortargumenten von Python merken
[Python] Was ich getan habe, um Unit Test zu machen
Python: Ich konnte in Lambda rekursieren
Ich möchte mit Python eine E-Mail von Google Mail senden.
Wenn ich matplotlib in Python versuche, heißt es'cairo.Context '.
[Python] Ich möchte 7DaysToDie von Discord aus verwalten! 1/3
Minimale Implementierung von Union Find in Python
Ich möchte ein Spiel mit Python machen
Geschrieben "Einführung in die Effektüberprüfung" in Python
Ich möchte DB-Informationen in einer Liste speichern