Cómo terminar un script de Python


1079

Soy consciente del die()comando en PHP que sale temprano de un script.

¿Cómo puedo hacer esto en Python?

Respuestas:


1418
import sys
sys.exit()

detalles de la sysdocumentación del módulo :

sys.exit([arg])

Salga de Python. Esto se implementa planteando la SystemExitexcepción, por lo que se respetan las acciones de limpieza especificadas por las cláusulas finales de las trydeclaraciones, y es posible interceptar el intento de salida a un nivel externo.

El argumento opcional arg puede ser un número entero que proporciona el estado de salida (predeterminado a cero) u otro tipo de objeto. Si es un número entero, cero se considera "terminación exitosa" y cualquier valor distinto de cero se considera "terminación anormal" por shells y similares. La mayoría de los sistemas requieren que esté en el rango de 0 a 127 y, de lo contrario, produce resultados indefinidos. Algunos sistemas tienen una convención para asignar significados específicos a códigos de salida específicos, pero estos generalmente están subdesarrollados; Los programas Unix generalmente usan 2 para errores de sintaxis de línea de comandos y 1 para todos los demás tipos de errores. Si se pasa otro tipo de objeto, Ninguno es equivalente a pasar cero, y cualquier otro objeto se imprime stderry da como resultado un código de salida de 1. En particular, sys.exit("some error message") es una forma rápida de salir de un programa cuando ocurre un error.

Como exit()finalmente "solo" genera una excepción, solo saldrá del proceso cuando se llame desde el hilo principal, y la excepción no se intercepta.

Tenga en cuenta que esta es la forma "agradable" de salir. @ glyphtwistedmatrix a continuación señala que si desea una 'salida dura', puede usar os._exit(*errorcode*), aunque es probable que sea específico del sistema operativo en cierta medida (por ejemplo, puede que no tome un código de error en Windows), y definitivamente es menos amigable ya que no deja que el intérprete realice ninguna limpieza antes de que el proceso falle.


99
Presumiblemente sys.exit()no funciona (no mata el proceso, solo mata el hilo) si lo levanta un hilo de fondo.

@ cesium62: Sí, sys.exit()plantea una SystemExitexcepción en el hilo actual.
Dmitry Trofimov

13
¿Hay alguna manera de finalizar un script sin generar una excepción? Ya estoy pasando banderas relevantes del script con print a stdout tubería en Popen, por lo que la excepción en este caso está causando más problemas de los que está resolviendo.
Elliot

44
¿Por qué, cuando uso este método me sale la siguiente advertencia:UserWarning: To exit: use 'exit', 'quit', or Ctrl-D. warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
Bill

1
Necesito más detalles; tal vez eso merece ser su propia pregunta?
pjz

349

Una manera simple de terminar un script Python temprano es usar la quit()función incorporada. No es necesario importar ninguna biblioteca, y es eficiente y simple.

Ejemplo:

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

86
también sys.exit () terminará todos los scripts de python, pero quit () solo termina el script que lo generó.
VishalDevgire

44
¿Sabes si este comando funciona de manera diferente en Python 2 y Python 3?
David C.

1
¿Alguien sabe si esto saldrá de todo el intérprete o solo hará que el script deje de ejecutarse? Específicamente: para un script que se ejecuta en Spyder, con el intérprete de Python permanecer interactivo, ¿o será eliminado? Intente simplemente detener la secuencia de comandos, pero deje la interactividad del intérprete presente.
Demis

3
para mí dice 'dejar de fumar' no está definido. Estoy usando Python 3.
Vincenzooo

44
Estoy en Python 3.7 y quit () detiene el intérprete y cierra el script.
RockAndRoleCoder

120

Otra forma es:

raise SystemExit

36
@Alessa: se ve más elegante, pero no se recomienda: está generando directamente una excepción incorporada en lugar del sys.exitenvoltorio preferible (y sobrescribible)
MestreLion

1
Esta es una manera perfecta para mí: simplemente salga del script en ejecución pero no salga de IDLE
rml


67

Si bien generalmente debería preferirlo sys.exitporque es más "amigable" con otro código, todo lo que realmente hace es generar una excepción.

Si está seguro de que necesita salir de un proceso de inmediato, y podría estar dentro de algún controlador de excepciones que se detectaría SystemExit, hay otra función os._exit, que finaliza inmediatamente en el nivel C y no realiza ninguna de las tareas normales de desmantelamiento. del intérprete; por ejemplo, los ganchos registrados con el módulo "atexit" no se ejecutan.


43

Me acabo de enterar cuando escribo una aplicación multiproceso, raise SystemExity sys.exit()ambos matan solo el hilo en ejecución. Por otro lado, os._exit()sale de todo el proceso. Esto se discutió en " ¿Por qué sys.exit () no sale cuando se llama dentro de un hilo en Python? ".

El siguiente ejemplo tiene 2 hilos. Kenny y Cartman. Se supone que Cartman vive para siempre, pero Kenny se llama de forma recursiva y debe morir después de 3 segundos. (Las llamadas recursivas no son la mejor manera, pero tenía otras razones)

Si también queremos que Cartman muera cuando Kenny muera, Kenny debería irse os._exit, de lo contrario, solo Kenny morirá y Cartman vivirá para siempre.

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
¡Esta parece ser la única forma de lidiar con las devoluciones de llamada diferidas desagradablemente! (es decir, métodos multiproceso.)
not2qubit

1
Bien hecho. Ninguna de las otras respuestas aborda directamente múltiples hilos, solo los scripts generan otros scripts.
anónimo el

33
from sys import exit
exit()

Como parámetro, puede pasar un código de salida, que se devolverá al sistema operativo. El valor predeterminado es 0.


3
en mi caso ni siquiera necesitaba importar la salida.
Kostanos

55
Solo para la posteridad en el comentario anterior, exit()y sys.exit()no son lo mismo. No use los exit()scripts incorporados , esto es solo una ayuda para el shell interactivo - usesys.exit()
daveruinseverything

18

Soy un novato total pero seguramente esto es más limpio y más controlado

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

if __name__ == '__main__': 
    main()

...

Programa terminado

que

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

...

Seguimiento finalizado del programa (última llamada más reciente): Archivo "Z: \ Directory \ testdieprogram.py", línea 12, en main () Archivo "Z: \ Directory \ testdieprogram.py", línea 8, en main sys.exit ( ) SystemExit

Editar

El punto es que el programa termina sin problemas y pacíficamente, en lugar de "¡HE DETENIDO!"


20
Un problema sería que si está en funciones anidadas y solo quiere salir, debe enviar una bandera hasta la función superior o volverá al siguiente nivel.
horta

11
Esto es una tontería absoluta si está tratando de sugerir que puede usar returnpara terminar el script. Todo lo que returnestá haciendo es devolver un valor y un flujo de control a la función de llamada. Allí continúa con la ejecución justo después de la llamada de la función que llamó return. Por supuesto, si esta returnes la última declaración en su secuencia de comandos como en su ejemplo, entonces la secuencia de comandos termina inmediatamente después de que se llama.
David Ferenczy Rogožan

1
Hay un fuerte argumento para este enfoque: (1) "salir" del medio es posiblemente un "goto", de ahí una aversión natural; (2) "salir" en las bibliotecas es definitivamente una mala práctica (y cualquier cosa puede convertirse en una biblioteca), ya que lo que una biblioteca considera "irrecuperable" generalmente está bien para la persona que llama . (Nota: el uso de excepciones para las salidas es una solución práctica de Python para los desarrolladores de C / C ++ / Java que siempre llaman de manera inapropiada exit, por lo tanto, los programadores de Python pueden no notar tanto el olor de este código); y, por último, (3) código multiproceso (que los pythonistas han ignorado históricamente).
michael

8

En Python 3.5, traté de incorporar un código similar sin el uso de módulos (por ejemplo, sys, Biopy) que no sean los que están integrados para detener el script e imprimir un mensaje de error a mis usuarios. Aquí está mi ejemplo:

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

Más tarde, descubrí que es más sucinto arrojar un error:

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

Estoy completamente de acuerdo en que es mejor generar una excepción para cualquier error que pueda manejar la aplicación. Pero la pregunta era cómo terminar un script de Python, por lo que esta no es realmente una (nueva) respuesta a la pregunta.
Wovano

-1

Mis dos centavos.

Python 3.8.1, Windows 10, 64 bits.

sys.exit() no funciona directamente para mi

Tengo varios bucles nexted.

Primero declaro una variable booleana, a la que llamo immediateExit.

Entonces, al comienzo del código del programa escribo:

immediateExit = False

Luego, a partir de la excepción de bucle más interna (anidada), escribo:

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

Luego entro en la continuación inmediata del bucle externo, y antes de que el código ejecute cualquier otra cosa, escribo:

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

Dependiendo de la complejidad, a veces la declaración anterior debe repetirse también en las secciones excepto, etc.

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

El mensaje personalizado es también para mi depuración personal, ya que los números son para el mismo propósito: ver dónde realmente existe el script.

'CSV file corrupted 1.5.'

En mi caso particular, estoy procesando un archivo CSV, que no quiero que el software toque, si el software detecta que está dañado. Por lo tanto, para mí es muy importante salir de todo el script de Python inmediatamente después de detectar la posible corrupción.

Y siguiendo el sistema gradual que sale de todos los bucles me las arreglo para hacerlo.

Código completo: (se necesitaban algunos cambios porque es un código propietario para tareas internas):

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
Gracias por tu contribución, pero para mí esta respuesta no tiene sentido. Dado que solo publica algunos fragmentos de código en lugar de un ejemplo completo, es difícil entender lo que quiere decir. Con solo las líneas de código que publicó aquí, el script saldría inmediatamente. Solo puedo adivinar que tiene un bloque try-catch, que detecta la excepción SystemExit que ya se menciona en otras respuestas. Si reescribiera su respuesta con un ejemplo de trabajo completo de cómo saldría limpiamente de una aplicación (es decir, realizando algunas acciones de apagado necesarias), creo que su publicación podría ser una adición útil.
wovano

Gracias por tus comentarios. Ahora agregué la parte del código, que se refiere a las declaraciones de salida.
Mateo

Bien, esto le da un poco más de contexto :) Aunque ahora creo que su solución es en realidad una solución para patrones de programación muy malos. En primer lugar, nunca debe usar except:sin tipo de excepción. Si solo usa except Exception:(o incluso un tipo de excepción más detallado si es posible), sys.exit()funcionaría según lo previsto y no necesitaría esta solución.
wovano

En segundo lugar, parece que intentas hacer bastantes cosas en un método, o probablemente incluso en el ámbito de archivo global. Sería útil dividir su código en partes más pequeñas (funciones), por ejemplo: (1) cargar el archivo de entrada, (2) procesar datos y (3) escribir el archivo de salida. Luego, si el paso 1 fallara, omitiría los pasos 2 y 3. Podría generar una excepción en cualquier lugar durante el paso de carga y podría manejar la excepción en un solo lugar. El uso sys.exit()es realmente una especie de solución de último recurso para errores críticos. Solo mis dos centavos :)
wovano

En general, no veo una funcionalidad global de salida / detención en Python, y me veo obligado a hacerlo de esta manera. El archivo CSV es realmente crítico para mí, por lo que lo protejo por todos los medios posibles, incluso si los medios pueden parecer feos. Estoy leyendo la Guía de Python de Hichhicker para mejorar mi estilo.
Mateo
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.