Come terminare uno script Python


1079

Sono a conoscenza del die()comando in PHP che esce presto da uno script.

Come posso farlo in Python?

Risposte:


1418
import sys
sys.exit()

dettagli dalla sysdocumentazione del modulo :

sys.exit([arg])

Esci da Python. Ciò viene implementato sollevando l' SystemExiteccezione, quindi tryvengono onorate le azioni di pulizia specificate dalle clausole di dichiarazione di fine ed è possibile intercettare il tentativo di uscita a un livello esterno.

L'argomento facoltativo arg può essere un numero intero che fornisce lo stato di uscita (impostazione predefinita a zero) o un altro tipo di oggetto. Se è un numero intero, zero è considerato "terminazione riuscita" e qualsiasi valore diverso da zero è considerato "terminazione anomala" da shell e simili. La maggior parte dei sistemi richiede che sia compreso nell'intervallo 0-127 e che altrimenti produca risultati indefiniti. Alcuni sistemi hanno una convenzione per assegnare significati specifici a codici di uscita specifici, ma questi sono generalmente sottosviluppati; I programmi Unix usano generalmente 2 per gli errori di sintassi della riga di comando e 1 per tutti gli altri tipi di errori. Se viene passato un altro tipo di oggetto, Nessuno equivale a passare lo zero e qualsiasi altro oggetto viene stampato stderre genera un codice di uscita pari a 1. In particolare, sys.exit("some error message") è un modo rapido per uscire da un programma quando si verifica un errore.

Poiché alla exit()fine "solo" solleva un'eccezione, uscirà dal processo solo quando viene chiamato dal thread principale e l'eccezione non viene intercettata.

Nota che questo è il modo "carino" per uscire. @ glyphtwistedmatrix di seguito sottolinea che se si desidera una 'uscita difficile', è possibile utilizzare os._exit(*errorcode*), anche se è probabilmente specifico del sistema operativo (ad esempio, potrebbe non prendere un codice di errore sotto Windows, ad esempio), e sicuramente è meno amichevole poiché non consente all'interprete di eseguire alcuna pulizia prima della fine del processo.


9
Presumibilmente sys.exit()non funziona (non uccide il processo, uccide solo il thread) se generato da un thread in background?

@ cesium62: Sì, sys.exit()solleva SystemExitun'eccezione nel thread corrente.
Dmitry Trofimov,

13
C'è un modo per terminare una sceneggiatura senza sollevare un'eccezione? Sto già passando bandiere rilevanti fuori dallo script con la stampa a tubazioni stdout in Popen, quindi l'eccezione in questo caso sta causando più problemi di quanti ne stia risolvendo.
Elliot

4
Perché, quando uso questo metodo, ricevo il seguente avviso:UserWarning: To exit: use 'exit', 'quit', or Ctrl-D. warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
Fattura

1
Hai bisogno di maggiori dettagli; forse questo merita di essere una sua domanda?
pjz,

349

Un modo semplice per terminare anticipatamente uno script Python consiste nell'utilizzare la quit()funzione integrata. Non è necessario importare alcuna libreria ed è efficiente e semplice.

Esempio:

#do stuff
if this == that:
  quit()

86
anche sys.exit () termina tutti gli script Python, ma quit () termina solo lo script che lo ha generato.
VishalDevgire,

4
Sai se questo comando funziona in modo diverso in Python 2 e Python 3?
David C.,

1
Qualcuno sa se questo uscirà da tutto l'interprete o farà semplicemente interrompere l'esecuzione dello script? In particolare: per uno script in esecuzione su Spyder, con l'interprete Python rimarrà interattivo o verrà ucciso? Cerca di fermare la continuazione dello script, ma lascia l'interattività dell'interprete presente.
Demis,

3
per me dice "smettere" non è definito. Sto usando Python 3.
Vincenzooo,

4
Sono in Python 3.7 e quit () arresta l'interprete e chiude lo script.
RockAndRoleCoder

120

Un altro modo è:

raise SystemExit

36
@Alessa: sembra più elegante, ma non è raccomandato: stai sollevando direttamente un'eccezione incorporata invece del sys.exitwrapper preferibile (e sovrascrivibile)
MestreLion

1
Questo è un modo perfetto per me: basta uscire dallo script in esecuzione ma non uscire da IDLE
rml


67

Mentre generalmente dovresti preferire sys.exitperché è più "amichevole" con altri codici, tutto ciò che fa è sollevare un'eccezione.

Se sei sicuro di dover uscire immediatamente da un processo e potresti trovarti all'interno di un gestore di eccezioni che potrebbe catturare SystemExit, c'è un'altra funzione os._exit- che termina immediatamente a livello C e non esegue alcun normale smontaggio dell'interprete; ad esempio, gli hook registrati con il modulo "atexit" non vengono eseguiti.


43

Ho appena scoperto che quando si scrive un'applicazione multithreadded, raise SystemExite sys.exit()sia uccide solo il filo conduttore. D'altra parte, os._exit()esce l'intero processo. Questo è stato discusso in " Perché sys.exit () non esce quando viene chiamato all'interno di un thread in Python? ".

L'esempio seguente ha 2 thread. Kenny e Cartman. Cartman dovrebbe vivere per sempre, ma Kenny è chiamato ricorsivamente e dovrebbe morire dopo 3 secondi. (la chiamata ricorsiva non è il modo migliore, ma ho avuto altri motivi)

Se vogliamo anche che Cartman muoia quando Kenny muore, Kenny dovrebbe andarsene os._exit, altrimenti morirà solo Kenny e Cartman vivrà per sempre.

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

1
Questo sembra essere l'unico modo per gestire le richiamate odiosamente posticipate! (ovvero metodi multi-thread.)
not2qubit

1
Molto bene. Nessuna delle altre risposte indirizza direttamente più thread, solo script che generano altri script.
anonimo

33
from sys import exit
exit()

Come parametro è possibile passare un codice di uscita, che verrà restituito al sistema operativo. L'impostazione predefinita è 0.


3
nel mio caso non avevo nemmeno bisogno di importare exit.
Kostanos,

5
Solo per i posteri sul commento sopra - exit()e sys.exit()non sono la stessa cosa. Non usare gli exit()script integrati , questo è solo un aiuto per la shell interattiva - usasys.exit()
daveruinseverything

18

Sono un principiante assoluto, ma sicuramente questo è più pulito e più controllato

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

if __name__ == '__main__': 
    main()

...

Programma terminato

di

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

...

Traceback terminato dal programma (ultima chiamata più recente): file "Z: \ Directory \ testdieprogram.py", riga 12, in main () File "Z: \ Directory \ testdieprogram.py", riga 8, in main sys.exit ( ) SystemExit

modificare

Il punto è che il programma termina senza intoppi e in modo pacifico, piuttosto che "HO FERMATO !!!!"


20
Un problema potrebbe essere se sei nelle funzioni nidificate e vuoi solo uscire, o devi inviare un flag fino alla funzione superiore o tornerai al livello successivo.
horta,

11
Questa è un'assurdità assoluta se stai cercando di suggerire che puoi usare returnper terminare lo script. Tutto returnciò che sta facendo è restituire un valore e un flusso di controllo alla funzione chiamante. Lì continua con l'esecuzione subito dopo la chiamata della funzione che ha chiamato return. Ovviamente, se returnè l'ultima affermazione nel tuo script come nel tuo esempio, allora lo script viene terminato subito dopo essere stato chiamato.
David Ferenczy Rogožan,

1
C'è un argomento forte da sostenere per questo approccio: (1) "uscita" dal centro è probabilmente un "goto", quindi un'avversione naturale; (2) "exit" nelle librerie è sicuramente una cattiva pratica (e tutto può diventare una libreria), dal momento che ciò che una libreria considera "irrecuperabile" di solito va bene al chiamante . (Nota: l'uso delle eccezioni per le uscite è una soluzione pratica di Python per gli sviluppatori C / C ++ / Java che chiamano sempre in modo inappropriato exit, quindi i programmatori di Python potrebbero non notare l'odore di questo odore di codice); e, infine, (3) codice multi-thread (che i pitonisti hanno storicamente appena ignorato).
michael

8

In Python 3.5, ho cercato di incorporare un codice simile senza utilizzare moduli (ad esempio sys, Biopy) diversi da quelli integrati per interrompere lo script e stampare un messaggio di errore per i miei utenti. Ecco il mio esempio:

## 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

Più tardi, ho scoperto che è più conciso lanciare un errore:

## My example revised:
if "ATG" in my_DNA: 
    ## <Do something & proceed...>
else: 
    raise ValueError("Start codon is missing! Check your DNA sequence!")

Sono completamente d'accordo sul fatto che è meglio sollevare un'eccezione per qualsiasi errore che può essere gestito dall'applicazione. Ma la domanda era come terminare uno script Python, quindi questa non è davvero una (nuova) risposta alla domanda.
wovano,

-1

I miei due centesimi.

Python 3.8.1, Windows 10, 64 bit.

sys.exit() non funziona direttamente per me.

Ho diversi loop successivi.

Per prima cosa dichiaro una variabile booleana, che chiamo immediateExit.

Quindi, all'inizio del codice del programma scrivo:

immediateExit = False

Quindi, a partire dall'eccezione del ciclo più interna (nidificata), scrivo:

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

Quindi vado nella continuazione immediata del ciclo esterno, e prima che qualsiasi altra cosa venga eseguita dal codice, scrivo:

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

A seconda della complessità, a volte l'istruzione sopra deve essere ripetuta anche nelle sezioni tranne, ecc.

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

Il messaggio personalizzato è anche per il mio debug personale, poiché i numeri hanno lo stesso scopo: vedere dove esce davvero lo script.

'CSV file corrupted 1.5.'

Nel mio caso particolare sto elaborando un file CSV, che non voglio che il software tocchi, se il software rileva che è danneggiato. Pertanto per me è molto importante uscire dall'intero script Python immediatamente dopo aver rilevato la possibile corruzione.

E seguendo il graduale sys.exiting da tutti i loop riesco a farlo.

Codice completo: (sono necessarie alcune modifiche perché è un codice proprietario per le attività interne):

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.')

1
Grazie per il tuo contributo, ma per me questa risposta non ha senso. Dato che pubblichi solo alcuni frammenti di codice anziché un esempio completo, è difficile capire cosa intendi. Con solo le righe di codice che hai pubblicato qui, lo script uscirà immediatamente. Posso solo supporre che tu abbia un blocco try-catch, che intercetta l'eccezione SystemExit che è già menzionata in altre risposte. Se dovessi riscrivere la tua risposta con un esempio funzionante completo di come uscire in modo pulito da un'applicazione (ovvero eseguendo alcune azioni di arresto necessarie), penso che il tuo post potrebbe essere un'aggiunta utile.
wovano,

Grazie per il tuo feedback. Ora ho aggiunto la parte del codice, che riguarda le dichiarazioni di uscita.
Matteo

Va bene, questo dà un po 'più contesto :) Anche se ora penso che la tua soluzione sia in realtà una soluzione per schemi di programmazione molto cattivi. Prima di tutto, non dovresti mai usare except:senza un tipo di eccezione. Se usi semplicemente except Exception:(o anche un tipo di eccezione più dettagliato, se possibile), sys.exit()funzionerebbe come previsto e non avresti bisogno di questa soluzione.
mercoledì

In secondo luogo, sembra che tu provi a fare parecchie cose in un solo metodo, o probabilmente anche nell'ambito dei file globali. Aiuterebbe a scomporre il codice in parti (funzioni) più piccole, ad esempio: (1) carica il file di input, (2) elabora i dati e (3) scrive il file di output. Quindi, se il passaggio 1 fallisce, salteresti i passaggi 2 e 3. Potresti sollevare un'eccezione ovunque durante il passaggio di caricamento e puoi gestire l'eccezione in un unico posto. L'utilizzo sys.exit()è davvero una sorta di soluzione di ultima istanza per errori critici. Solo i miei due centesimi :)
wovano il

In generale, non vedo una funzionalità di uscita / arresto globale in Python e sono costretto a farlo in questo modo. Il file CSV è davvero fondamentale per me, quindi lo custodisco con ogni mezzo possibile, anche se il mezzo potrebbe sembrare brutto. Sto leggendo The Hichhicker's Guide to Python per migliorare il mio stile.
Matteo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.