¡Hoy, nos sumergiremos en el tema de salir / terminar los scripts de Python! Antes de comenzar, debe tener una comprensión básica de lo que es Python y algunos conocimientos básicos sobre su uso.

Puede usar el IDE de su elección, pero esta vez usaré el paquete Subsistema Linux para Windows (WSL) de Microsoft. Para obtener más información sobre eso y cómo lo habilita en Windows 10, vaya aquí .

¿Por qué Python sale automáticamente de una secuencia de comandos cuando está lista?

La forma en que Python ejecuta un bloque de código hace que ejecute cada línea en orden, verificando las dependencias para importar, leyendo definiciones y clases para almacenar en la memoria, y ejecutando fragmentos de código en orden permitiendo bucles y llamadas a las definiciones y clases definidas.

Cuando el intérprete de Python llega al final del archivo (EOF), se da cuenta de que no puede leer más datos de la fuente, ya sea la entrada del usuario a través de un IDE o la lectura de un archivo. Para demostrarlo, intentemos obtener información del usuario e interrumpir al intérprete en medio de la ejecución.

Primero, desde su terminal bash en su PowerShell, abra un nuevo archivo llamado "input.py"

1
$ nano input.py

Luego pegue lo siguiente en el shell haciendo clic derecho en la ventana de PowerShell

1
2
3
name=input("Don't type anything!\n")
 
print("Hi,",name,"!")

Ahora, presione CTRL+Xpara guardar y salir de la ventana nano y en su tipo de shell:

1
2
$ python3 input.py
Don't type anything!

Y presione  CTRL+D para terminar el programa mientras espera la entrada del usuario

1
2
3
4
5
6
7
Traceback (most recent call last):
 
File "input.py", line 1, in
 
    name=input("Don't type anything!")
 
EOFError

La  EOFError excepción nos dice que el intérprete de Python alcanzó la condición de final de archivo (EOF) antes de terminar de ejecutar el código, ya que el usuario no ingresó datos de entrada.

Cuando Python alcanza la condición EOF al mismo tiempo que ha ejecutado todo el código, sale sin lanzar ninguna excepción, que es una de las formas en que Python puede salir "con gracia".

Detectar salida de script

Si queremos saber cuándo sale un programa Python sin lanzar una excepción, podemos usar el atexitmódulo Python incorporado .

El atexitmaneja todo lo que queremos que haga el programa cuando sale y generalmente se usa para limpiar el programa antes de que finalice el proceso del programa.

Para experimentar con atexit, modifiquemos nuestro ejemplo input.py para imprimir un mensaje al salir del programa. Abra el archivo input.py nuevamente y reemplace el texto con este

1
2
3
4
5
6
7
import atexit
 
atexit.register(print,"Program exited successfully!")
 
name=input("What's your name?\n")
 
print("Hi,",name,"!")

Escriba su nombre y cuando presione enter debería obtener:

1
2
3
4
What's your name?
Example
Hi, Example !
Program exited successfully!

Observe cómo el texto de salida aparece al final de la salida sin importar dónde coloquemos la  atexit llamada, y cómo si reemplazamos la  atexit llamada con un simple  print(), obtenemos el texto de salida donde print() se hizo todo, en lugar de donde sale el código.

1
2
3
4
Program exited successfully!
What's your name?
Example
Hi, Example !

Salida elegante

Hay varias formas de salir de un programa Python que no implican lanzar una excepción, la primera que iba a intentar es quit()

Puede usar el comando bash echo $? para obtener el código de salida del intérprete de Python.

1
2
3
4
5
6
7
$ python3
Python 3.8.2 (default, Apr  1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()
$ echo $?
0

También podemos definir el tipo de código con el que debe salir el intérprete entregando  quit() un argumento entero menor que 256

1
2
3
4
5
6
7
$ python3
Python 3.8.2 (default, Apr  1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> quit(101)
$ echo $?
101

exit() tiene la misma funcionalidad que es un alias para quit()

1
2
3
4
5
6
7
$ python3
Python 3.8.2 (default, Apr  1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit(101)
$ echo $?
101

Ni  quit() tampoco  exit() se considera una buena práctica, ya que ambos requieren el  site módulo que está destinado a ser utilizado para los intérpretes interactivos y no en los programas. Para nuestros programas, deberíamos usar algo como sys.exit

1
2
3
4
5
6
7
8
$ python3
Python 3.8.2 (default, Apr  1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.exit(101)
$ echo $?
101

Tenga en cuenta que necesitamos importar explícitamente un módulo para llamar  exit(), esto puede parecer que no es una mejora, pero garantiza que se cargue el módulo necesario porque no es una buena suposición siteque se cargará en tiempo de ejecución. Si no queremos importar módulos adicionales, podemos hacer qué  exit(),  quit() y lo  sys.exit() estamos haciendo detrás de escena y raise SystemExit

1
2
3
4
5
6
7
$ python3
Python 3.8.2 (default, Apr  1 2020, 15:52:55)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> raise SystemExit(101)
$ echo $?
101

Salir con mensajes de error

¿Qué pasa si recibimos una mala entrada de un usuario? Echemos un vistazo a nuestro  input.py script y agreguemos la capacidad de manejar la entrada incorrecta del usuario ( CTRL+D para pasar un carácter EOF)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
$ nano input.py
try:
 
    name=input("What's your name?\n")
 
    print("Hi, "+name+"!")
 
except EOFError:
 
    print("EOFError: You didn't enter anything!")
 
$ python3 input.py
What's your name?
EOFError: You didn't enter anything!

La  try declaración le dice a Python que pruebe el código dentro de la declaración y que pase cualquier excepción a la  except declaración antes de salir.

Salir sin error

¿Qué sucede si el usuario le entrega un error a su programa pero usted no quiere que su código imprima un error o que realice algún tipo de manejo de errores para minimizar el impacto del usuario?

Podemos agregar una finally declaración que nos permita ejecutar código después de hacer nuestro manejo de errores en catch

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
dieciséis
17
18
19
20
21
$ nano input.py
try:
 
    name=input("What's your name?\n")
 
    if(name==''):
 
        print("Name cannot be blank!")
 
except EOFError:
 
    #print("EOFError: You didn't enter anything!")
    name="Blankname"
 
finally:
 
    print("Hi, "+name+"!")
 
$ python3 input.py
What's your name?
Hi, Blankname!

Tenga en cuenta que el usuario nunca sabrá que ha  EOFErrorocurrido, esto se puede usar para pasar valores predeterminados en caso de entrada o argumentos deficientes.

Salga y libere sus recursos

Generalmente, Python libera todos los recursos que ha llamado en su programa automáticamente cuando sale, pero para ciertos procesos, es una buena práctica incluir algunos recursos limitados en un with bloque.

A menudo verá esto en las  open() llamadas, donde no liberar correctamente el archivo podría causar problemas para leer o escribir en el archivo más tarde.

1
2
3
4
5
6
7
8
$ nano openfile.py
with open("testfile.txt","w") as file:
 
    file.write("let's write some text!\n")
 
$ python3 openfile.py
$ cat testfile.txt
let's write some text!

El  withbloque libera automáticamente todos los recursos solicitados dentro de él. Si quisiéramos asegurarnos de manera más explícita que el archivo se cerró, podemos usar el  atexit.register() comando para llamar close()

1
2
3
4
5
6
7
8
$ nano openfile.py
import atexit
 
file=open("testfile.txt","w")
 
file.write("let's write some text!\n")
 
atexit.register(file.close)

Si los recursos se llaman sin usar un  with bloque, asegúrese de liberarlos explícitamente en un  atexit comando.

Salir después de un tiempo

Si nos preocupa que nuestro programa nunca termine normalmente, entonces podemos usar el multiprocessingmódulo de Python  para asegurarnos de que nuestro programa terminará.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
dieciséis
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ nano waiting.py
import time
 
import sys
 
from multiprocessing import Process
 
integer=sys.argv[1]
 
init=map(int, integer.strip('[]'))
 
num=list(init)[0]
 
def exclaim(int):
 
    time.sleep(int)
 
    print("You were very patient!")
 
if __name__ == '__main__':
 
    program = Process(target=exclaim, args=(num,))
 
    program.start()
 
    program.join(timeout=5)
 
    program.terminate()
 
$ python3 waiting.py 7
$ python3 waiting.py 0
You were very patient!

¡Observe cómo el proceso no se completó cuando se le dijo a la función que esperara 7 segundos, pero se completó e imprimió lo que se suponía que debía hacer cuando se le dijo que esperara 0 segundos!

Salir usando una declaración de devolución

Si tenemos una sección de código que queremos usar para terminar todo el programa, en lugar de dejar que la  breakdeclaración continúe el código fuera del ciclo, podemos usar return sys.exit() para salir del código por completo.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
dieciséis
17
18
19
20
21
22
23
24
$ nano break.py
import time
 
import sys
 
def stop(isTrue):
 
    for a in range(0,1):
 
        if isTrue:
 
            break
 
        else:
 
            print("You didn't want to break!")
 
            return sys.exit()
 
mybool = False
 
stop(mybool)
 
print("You used break!")

Salir en medio de una función

Si no queremos usar una declaración de retorno, aún podemos llamar a sys.exit() para cerrar nuestro programa y proporcionar un  return en otra rama. Usemos nuestro código de break.py nuevamente.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
dieciséis
17
18
19
20
21
22
23
24
$ nano break.py
import time
 
import sys
 
def stop(isTrue):
 
    for a in range(0,1):
 
        if isTrue:
 
            word="bird"
 
            break
 
        else:
 
            print("You didn't want to break!")
 
            sys.exit()
 
mybool = False
 
print(stop(mybool))

Salir cuando se cumplan las condiciones

Si tenemos un bucle en nuestro código Python y queremos asegurarnos de que el código pueda salir si encuentra un problema, podemos usar una bandera que pueda verificar para terminar el programa.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
dieciséis
17
18
19
20
21