So beenden Sie ein Python-Skript

1078

Mir ist der die()Befehl in PHP bekannt, der ein Skript vorzeitig beendet.

Wie kann ich das in Python machen?

Teifion
quelle

Antworten:

1417
import sys
sys.exit()

Details aus der sysModuldokumentation :

sys.exit([arg])

Beenden Sie Python. Dies wird durch Auslösen der SystemExitAusnahme implementiert , sodass Bereinigungsaktionen, die in den Klauseln "finally" von tryAnweisungen angegeben sind, berücksichtigt werden und der Exit-Versuch auf einer äußeren Ebene abgefangen werden kann.

Das optionale Argument arg kann eine Ganzzahl sein, die den Exit-Status angibt (standardmäßig Null), oder ein anderer Objekttyp. Wenn es sich um eine Ganzzahl handelt, wird Null als "erfolgreiche Beendigung" betrachtet, und jeder Wert ungleich Null wird von Schalen und dergleichen als "abnormale Beendigung" angesehen. Die meisten Systeme erfordern einen Bereich zwischen 0 und 127 und führen ansonsten zu undefinierten Ergebnissen. Einige Systeme haben eine Konvention zum Zuweisen bestimmter Bedeutungen zu bestimmten Exit-Codes, aber diese sind im Allgemeinen unterentwickelt. Unix-Programme verwenden im Allgemeinen 2 für Befehlszeilensyntaxfehler und 1 für alle anderen Arten von Fehlern. Wenn ein anderer Objekttyp übergeben wird, entspricht None dem Übergeben von Null, und jedes andere Objekt wird gedruckt stderrund führt zu einem Exit-Code von 1. Insbesondere sys.exit("some error message") ist eine schnelle Möglichkeit, ein Programm zu beenden, wenn ein Fehler auftritt.

Da exit()letztendlich "nur" eine Ausnahme auslöst, wird der Prozess nur beendet, wenn er vom Hauptthread aufgerufen wird, und die Ausnahme wird nicht abgefangen.

Beachten Sie, dass dies der "schöne" Weg zum Beenden ist. @ glyphtwistedmatrix unten weist darauf hin, dass Sie, wenn Sie einen "harten Ausgang" wünschen, diesen verwenden können os._exit(*errorcode*), obwohl er wahrscheinlich bis zu einem gewissen Grad os-spezifisch ist (unter Windows wird möglicherweise kein Fehlercode verwendet), und er ist definitiv weniger freundlich, da er lässt den Interpreter keine Bereinigung durchführen, bevor der Prozess beendet ist.

pjz
quelle
9
Funktioniert vermutlich sys.exit()nicht (beendet den Prozess nicht, beendet nur den Thread), wenn er von einem Hintergrund-Thread ausgelöst wird?
@ cesium62: Ja, sys.exit()löst eine SystemExitAusnahme im aktuellen Thread aus.
Dmitry Trofimov
13
Gibt es eine Möglichkeit, ein Skript zu beenden, ohne eine Ausnahme auszulösen? Ich übergebe bereits relevante Flags aus dem Skript mit print an stdout piping in Popen, sodass die Ausnahme in diesem Fall mehr Probleme verursacht als löst.
Elliot
4
Warum, wenn ich diese Methode verwende, erhalte ich die folgende Warnung:UserWarning: To exit: use 'exit', 'quit', or Ctrl-D. warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
Bill
1
Benötigen Sie weitere Details; Vielleicht verdient das eine eigene Frage?
pjz
349

Eine einfache Möglichkeit, ein Python-Skript vorzeitig zu beenden, ist die Verwendung der integrierten quit()Funktion. Es ist nicht erforderlich, eine Bibliothek zu importieren, und sie ist effizient und einfach.

Beispiel:

#do stuff
if this == that:
  quit()
jmgr
quelle
86
Auch sys.exit () beendet alle Python-Skripte, aber quit () beendet nur das Skript, das es erzeugt hat.
VishalDevgire
4
Wissen Sie, ob dieser Befehl in Python 2 und Python 3 unterschiedlich funktioniert?
David C.
1
Weiß jemand, ob dies den gesamten Interpreter beendet oder nur dazu führt, dass das Skript nicht mehr ausgeführt wird? Speziell: Für ein Skript, das in Spyder ausgeführt wird, bleibt der Python-Interpreter interaktiv, oder wird er beendet? Versuchen Sie einfach, die Fortsetzung des Skripts zu verhindern, lassen Sie jedoch die Interaktivität des Interpreters vorhanden.
Demis
3
Für mich heißt es, dass "Beenden" nicht definiert ist. Ich benutze Python 3.
Vincenzooo
4
Ich bin in Python 3.7 und quit () stoppt den Interpreter und schließt das Skript.
RockAndRoleCoder
120

Ein anderer Weg ist:

raise SystemExit
Vhaerun
quelle
36
@Alessa: es sieht eleganter aus, aber es wird nicht empfohlen: Sie lösen direkt eine eingebaute Ausnahme anstelle des bevorzugten (und überschreibbaren) sys.exitWrappers
MestreLion
1
Dies ist ein perfekter Weg für mich: Beenden Sie einfach das laufende Skript, aber nicht das IDLE
rml
77

Sie können auch einfach verwenden exit().

Beachten Sie, dass sys.exit(), exit(), quit(), und os._exit(0) töten den Python - Interpreter. Wenn es in einem Skript angezeigt wird, das von einem anderen Skript von aufgerufen wurde execfile(), stoppt es daher die Ausführung beider Skripte.

Siehe " Ausführung eines mit execfile aufgerufenen Skripts stoppen ", um dies zu vermeiden.

Weltraum-Cowboy
quelle
67

Während Sie im Allgemeinen bevorzugen sollten, sys.exitweil es für anderen Code "freundlicher" ist, löst es tatsächlich nur eine Ausnahme aus.

Wenn Sie sicher sind, dass Sie einen Prozess sofort beenden müssen und sich möglicherweise in einem Ausnahmebehandler befinden, der abfangen würde SystemExit, gibt es eine andere Funktion - os._exit-, die sofort auf der C-Ebene beendet wird und keinen der normalen Abrisse ausführt des Dolmetschers; Beispielsweise werden mit dem Modul "atexit" registrierte Hooks nicht ausgeführt.

Glyphe
quelle
43

Ich habe gerade herausgefunden, dass , wenn eine multithreadded App schreiben, raise SystemExitund sys.exit()beide nur den laufenden Faden tötet. Beendet andererseits os._exit()den gesamten Prozess. Dies wurde unter " Warum wird sys.exit () nicht beendet, wenn es in einem Thread in Python aufgerufen wird? " Erläutert .

Das folgende Beispiel hat 2 Threads. Kenny und Cartman. Cartman soll für immer leben, aber Kenny wird rekursiv gerufen und sollte nach 3 Sekunden sterben. (rekursives Aufrufen ist nicht der beste Weg, aber ich hatte andere Gründe)

Wenn wir auch wollen, dass Cartman stirbt, wenn Kenny stirbt, sollte Kenny weggehen os._exit, sonst wird nur Kenny sterben und Cartman wird für immer leben.

import threading
import time
import sys
import os

def kenny(num=0):
    if num > 3:
        # print("Kenny dies now...")
        # raise SystemExit #Kenny will die, but Cartman will live forever
        # sys.exit(1) #Same as above

        print("Kenny dies and also kills Cartman!")
        os._exit(1)
    while True:
        print("Kenny lives: {0}".format(num))
        time.sleep(1)
        num += 1
        kenny(num)

def cartman():
    i = 0
    while True:
        print("Cartman lives: {0}".format(i))
        i += 1
        time.sleep(1)

if __name__ == '__main__':
    daemon_kenny = threading.Thread(name='kenny', target=kenny)
    daemon_cartman = threading.Thread(name='cartman', target=cartman)
    daemon_kenny.setDaemon(True)
    daemon_cartman.setDaemon(True)

    daemon_kenny.start()
    daemon_cartman.start()
    daemon_kenny.join()
    daemon_cartman.join()
eaydin
quelle
1
Dies scheint der einzige Weg zu sein, um mit widerlich zurückgestellten Rückrufen umzugehen! (dh Multithread-Methoden.)
not2qubit
1
Gut gemacht. Keine der anderen Antworten adressiert direkt mehrere Threads, nur Skripte, die andere Skripte erzeugen.
anonym
33
from sys import exit
exit()

Als Parameter können Sie einen Exit-Code übergeben, der an das Betriebssystem zurückgegeben wird. Standard ist 0.

cleg
quelle
3
In meinem Fall musste ich Exit nicht einmal importieren.
Kostanos
5
Nur für die Nachwelt zum obigen Kommentar - exit()und sys.exit()sind nicht dasselbe. Verwenden Sie nicht die eingebauten exit()Skripte, dies ist nur ein Helfer für die interaktive Shell - verwenden Siesys.exit()
daveruinseverything
18

Ich bin ein absoluter Neuling, aber das ist sicherlich sauberer und kontrollierter

def main():
    try:
        Answer = 1/0
        print  Answer
    except:
        print 'Program terminated'
        return
    print 'You wont see this'

if __name__ == '__main__': 
    main()

...

Programm beendet

als

import sys
def main():
    try:
        Answer = 1/0
        print  Answer
    except:
        print 'Program terminated'
        sys.exit()
    print 'You wont see this'

if __name__ == '__main__': 
    main()

...

Programm beendet Traceback (letzter Aufruf zuletzt): Datei "Z: \ Directory \ testdieprogram.py", Zeile 12, in main () Datei "Z: \ Directory \ testdieprogram.py", Zeile 8, in main sys.exit ( ) SystemExit

Bearbeiten

Der Punkt ist, dass das Programm reibungslos und friedlich endet, anstatt "Ich habe aufgehört !!!!"

Floggedhorse
quelle
20
Ein Problem wäre, wenn Sie sich in verschachtelten Funktionen befinden und nur beenden möchten, müssen Sie entweder ein Flag bis zur obersten Funktion zurücksenden oder Sie kehren einfach zur nächsten Ebene zurück.
Horta
11
Dies ist ein absoluter Unsinn, wenn Sie vorschlagen möchten, dass Sie returndas Skript beenden können. Sie müssen returnlediglich einen Wert und einen Steuerungsfluss an die aufrufende Funktion zurückgeben. Dort wird direkt nach dem Aufruf der aufgerufenen Funktion mit der Ausführung fortgefahren return. Wenn dies die returnletzte Anweisung in Ihrem Skript wie in Ihrem Beispiel ist, wird das Skript natürlich direkt nach dem Aufruf beendet.
David Ferenczy Rogožan
1
Es gibt ein starkes Argument für diesen Ansatz: (1) "Austritt" aus der Mitte ist wohl ein "Goto", daher eine natürliche Abneigung; (2) "Beenden" in Bibliotheken ist definitiv eine schlechte Praxis (und alles kann zu einer Bibliothek werden), da das, was eine Bibliothek als "nicht wiederherstellbar" ansieht, für den Anrufer normalerweise in Ordnung ist . (Hinweis: Die Verwendung von Ausnahmen für Exits ist eine praktische Umgehung von Python für C / C ++ / Java-Entwickler, die immer unangemessen aufrufen. exitDaher bemerken Python-Programmierer den Gestank dieses Codes möglicherweise nicht so stark.) und schließlich (3) Multithread-Code (den Pythonisten in der Vergangenheit einfach ignoriert haben).
Michael
8

In Python 3.5 habe ich versucht, ähnlichen Code ohne Verwendung von Modulen (z. B. sys, Biopy) zu integrieren, außer den integrierten, um das Skript zu stoppen und eine Fehlermeldung an meine Benutzer zu drucken. Hier ist mein Beispiel:

## My example:
if "ATG" in my_DNA: 
    ## <Do something & proceed...>
else: 
    print("Start codon is missing! Check your DNA sequence!")
    exit() ## as most folks said above

Später fand ich es prägnanter, nur einen Fehler zu werfen:

## My example revised:
if "ATG" in my_DNA: 
    ## <Do something & proceed...>
else: 
    raise ValueError("Start codon is missing! Check your DNA sequence!")
David C.
quelle
Ich stimme voll und ganz zu, dass es besser ist, eine Ausnahme für jeden Fehler auszulösen, der von der Anwendung behandelt werden kann. Die Frage war jedoch, wie ein Python-Skript beendet werden kann. Dies ist also keine (neue) Antwort auf die Frage.
Wovano
-1

Meine zwei Cent.

Python 3.8.1, Windows 10, 64-Bit.

sys.exit() funktioniert nicht direkt bei mir.

Ich habe mehrere nächste Schleifen.

Zuerst deklariere ich eine boolesche Variable, die ich aufrufe immediateExit.

Also schreibe ich am Anfang des Programmcodes:

immediateExit = False

Ausgehend von der innersten (verschachtelten) Schleifenausnahme schreibe ich dann:

            immediateExit = True
            sys.exit('CSV file corrupted 0.')

Dann gehe ich in die unmittelbare Fortsetzung der äußeren Schleife und bevor etwas anderes vom Code ausgeführt wird, schreibe ich:

    if immediateExit:
        sys.exit('CSV file corrupted 1.')

Abhängig von der Komplexität muss die obige Aussage manchmal auch in Ausnahmeabschnitten usw. wiederholt werden.

    if immediateExit:
        sys.exit('CSV file corrupted 1.5.')

Die benutzerdefinierte Nachricht ist auch für mein persönliches Debugging gedacht, da die Nummern dem gleichen Zweck dienen - um zu sehen, wo das Skript wirklich beendet wird.

'CSV file corrupted 1.5.'

In meinem speziellen Fall verarbeite ich eine CSV-Datei, die die Software nicht berühren soll, wenn die Software feststellt, dass sie beschädigt ist. Daher ist es für mich sehr wichtig, das gesamte Python-Skript sofort nach dem Erkennen der möglichen Beschädigung zu beenden.

Und nach dem allmählichen Verlassen aller Schleifen schaffe ich es.

Vollständiger Code: (Einige Änderungen waren erforderlich, da es sich um proprietären Code für interne Aufgaben handelt.)

immediateExit = False
start_date = '1994.01.01'
end_date = '1994.01.04'
resumedDate = end_date


end_date_in_working_days = False
while not end_date_in_working_days:
    try:
        end_day_position = working_days.index(end_date)

        end_date_in_working_days = True
    except ValueError: # try statement from end_date in workdays check
        print(current_date_and_time())
        end_date = input('>> {} is not in the list of working days. Change the date (YYYY.MM.DD): '.format(end_date))
        print('New end date: ', end_date, '\n')
        continue


    csv_filename = 'test.csv'
    csv_headers = 'date,rate,brand\n' # not real headers, this is just for example
    try:
        with open(csv_filename, 'r') as file:
            print('***\nOld file {} found. Resuming the file by re-processing the last date lines.\nThey shall be deleted and re-processed.\n***\n'.format(csv_filename))
            last_line = file.readlines()[-1]
            start_date = last_line.split(',')[0] # assigning the start date to be the last like date.
            resumedDate = start_date

            if last_line == csv_headers:
                pass
            elif start_date not in working_days:
                print('***\n\n{} file might be corrupted. Erase or edit the file to continue.\n***'.format(csv_filename))
                immediateExit = True
                sys.exit('CSV file corrupted 0.')
            else:
                start_date = last_line.split(',')[0] # assigning the start date to be the last like date.
                print('\nLast date:', start_date)
                file.seek(0) # setting the cursor at the beginnning of the file
                lines = file.readlines() # reading the file contents into a list
                count = 0 # nr. of lines with last date
                for line in lines: #cycling through the lines of the file
                    if line.split(',')[0] == start_date: # cycle for counting the lines with last date in it.
                        count = count + 1
        if immediateExit:
            sys.exit('CSV file corrupted 1.')
        for iter in range(count): # removing the lines with last date
            lines.pop()
        print('\n{} lines removed from date: {} in {} file'.format(count, start_date, csv_filename))



        if immediateExit:
            sys.exit('CSV file corrupted 1.2.')
        with open(csv_filename, 'w') as file:
            print('\nFile', csv_filename, 'open for writing')
            file.writelines(lines)

            print('\nRemoving', count, 'lines from', csv_filename)

        fileExists = True

    except:
        if immediateExit:
            sys.exit('CSV file corrupted 1.5.')
        with open(csv_filename, 'w') as file:
            file.write(csv_headers)
            fileExists = False
    if immediateExit:
        sys.exit('CSV file corrupted 2.')
Matthew
quelle
1
Vielen Dank für Ihren Beitrag, aber für mich macht diese Antwort keinen Sinn. Da Sie nur ein paar Codeausschnitte anstelle eines vollständigen Beispiels veröffentlichen, ist es schwer zu verstehen, was Sie meinen. Mit nur den Codezeilen, die Sie hier gepostet haben, wird das Skript sofort beendet. Ich kann nur vermuten, dass Sie einen Try-Catch-Block haben, der die SystemExit-Ausnahme abfängt, die bereits in anderen Antworten erwähnt wurde. Wenn Sie Ihre Antwort mit einem voll funktionsfähigen Beispiel umschreiben würden, wie Sie eine Anwendung sauber beenden würden (dh indem Sie einige notwendige Aktionen zum Herunterfahren ausführen), könnte Ihr Beitrag eine nützliche Ergänzung sein.
Wovano
Vielen Dank für dein Feedback. Jetzt habe ich den Teil des Codes hinzugefügt, der die Exit-Anweisungen betrifft.
Matthew
Okay, das gibt ein bisschen mehr Kontext :) Obwohl ich jetzt denke, dass Ihre Lösung tatsächlich eine Problemumgehung für sehr schlechte Programmiermuster ist. Zunächst sollten Sie niemals except:ohne Ausnahmetyp verwenden. Wenn Sie nur except Exception:(oder wenn möglich sogar einen detaillierteren Ausnahmetyp) verwenden, sys.exit()funktioniert der wie vorgesehen und Sie benötigen diese Problemumgehung nicht.
Wovano
Zweitens scheint es so, als würden Sie versuchen, eine ganze Reihe von Dingen in einer Methode oder wahrscheinlich sogar im globalen Dateibereich auszuführen. Es wäre hilfreich, Ihren Code in kleinere Teile (Funktionen) aufzuteilen, zum Beispiel: (1) Eingabedatei laden, (2) Daten verarbeiten und (3) Ausgabedatei schreiben. Wenn dann Schritt 1 fehlschlagen würde, würden Sie die Schritte 2 und 3 überspringen. Sie könnten während des Ladeschritts an einer beliebigen Stelle eine Ausnahme auslösen und die Ausnahme an einer Stelle behandeln. Die Verwendung sys.exit()ist wirklich eine Art letzter Ausweg für kritische Fehler. Nur meine zwei Cent :)
Wovano
Im Allgemeinen sehe ich in Python keine globale Exit / Stopp-Funktionalität und bin gezwungen, dies so zu machen. Die CSV-Datei ist für mich sehr wichtig, daher bewahre ich sie auf jeden Fall, auch wenn die Mittel hässlich aussehen könnten. Ich lese den Hichhicker-Leitfaden zu Python , um meinen Stil zu verbessern.
Matthew