Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

374
Vistas
¿'Finalmente' siempre se ejecuta en Python?

Para cualquier bloque try-finally posible en Python, ¿está garantizado que el finally bloque siempre se ejecutará?

Por ejemplo, digamos que vuelvo mientras estoy en un bloque except :

 try: 1/0 except ZeroDivisionError: return finally: print("Does this code run?")

O tal vez vuelva a plantear una Exception :

 try: 1/0 except ZeroDivisionError: raise finally: print("What about this code?")

Las pruebas muestran que finally se ejecuta para los ejemplos anteriores, pero imagino que hay otros escenarios en los que no he pensado.

¿Hay algún escenario en el que un bloque finally no pueda ejecutarse en Python?

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

"Garantizado" es una palabra mucho más fuerte que cualquier implementación de finally merece. Lo que está garantizado es que si la ejecución fluye fuera de toda la construcción try - finally , pasará por la finally para hacerlo. Lo que no está garantizado es que la ejecución fluirá del try finally .

  • Es posible que nunca se ejecute una finally en un generador o una corrutina asíncrona , si el objeto nunca se ejecuta hasta el final. Hay muchas maneras en que eso podría suceder; Aquí hay uno:

     def gen(text): try: for line in text: try: yield int(line) except: # Ignore blank lines - but catch too much! pass finally: print('Doing important cleanup') text = ['1', '', '2', '', '3'] if any(n > 1 for n in gen(text)): print('Found a number') print('Oops, no cleanup.')

    Tenga en cuenta que este ejemplo es un poco complicado: cuando el generador se recolecta como basura, Python intenta ejecutar el bloque finally lanzando una excepción GeneratorExit , pero aquí detectamos esa excepción y luego yield nuevamente, momento en el que Python muestra una advertencia (" generador ignoró GeneratorExit") y se da por vencido. Consulte PEP 342 (rutinas a través de generadores mejorados) para obtener más detalles.

    Otras formas en que un generador o una corrutina podrían no ejecutarse hasta la conclusión incluyen si el objeto nunca se realiza en GC (sí, eso es posible, incluso en CPython), o si un async with await s en __aexit__ , o si el objeto await s o yield s en un bloque finally . Esta lista no pretende ser exhaustiva.

  • Un subproceso finally en un daemon podría no ejecutarse nunca si todos los subprocesos que no son daemon salen primero.

  • os._exit detendrá el proceso inmediatamente sin ejecutar finally los bloques.

  • os.fork puede causar que los bloques finally se ejecuten dos veces . Además de los problemas normales que cabría esperar de que las cosas sucedieran dos veces, esto podría causar conflictos de acceso simultáneos (bloqueos, bloqueos,...) si el acceso a los recursos compartidos no está correctamente sincronizado .

    Dado que el multiprocessing usa bifurcación sin ejecución para crear procesos de trabajo cuando se usa el método de inicio de bifurcación (el predeterminado en Unix), y luego llama a os._exit en el trabajador una vez que el trabajo del trabajador ha terminado, finally , la interacción de multiprocessing puede ser problemática ( ejemplo ).

  • Una falla de segmentación de nivel C evitará que se ejecuten finally los bloques.
  • kill -SIGKILL evitará que se ejecuten finally los bloques. SIGTERM y SIGHUP también evitarán que se ejecuten finally los bloques a menos que instale un controlador para controlar el apagado usted mismo; de forma predeterminada, Python no maneja SIGTERM o SIGHUP .
  • Una excepción en finally puede evitar que se complete la limpieza. Un caso particularmente digno de mención es si el usuario presiona control-C justo cuando comenzamos a ejecutar el bloque finally . Python generará una interrupción de KeyboardInterrupt y omitirá cada línea del contenido del bloque finally . ( KeyboardInterrupt -el código seguro es muy difícil de escribir).
  • Si la computadora pierde energía, o si hiberna y no se activa, finally los bloques no se ejecutarán.

El bloque finally no es un sistema de transacciones; no proporciona garantías de atomicidad ni nada por el estilo. Algunos de estos ejemplos pueden parecer obvios, pero es fácil olvidar que tales cosas pueden suceder y confiar demasiado en finally .

over 4 years ago · Santiago Trujillo Denunciar

0

Si. Finalmente siempre gana.

La única forma de vencerlo es detener la ejecución antes de que finally: tenga la oportunidad de ejecutar (por ejemplo, bloquee el intérprete, apague su computadora, suspenda un generador para siempre).

Me imagino que hay otros escenarios en los que no he pensado.

Aquí hay un par más en los que quizás no hayas pensado:

 def foo(): # finally always wins try: return 1 finally: return 2 def bar(): # even if he has to eat an unhandled exception, finally wins try: raise Exception('boom') finally: return 'no boom'

Dependiendo de cómo salga del intérprete, a veces puede "cancelar" finalmente, pero no así:

 >>> import sys >>> try: ... sys.exit() ... finally: ... print('finally wins!') ... finally wins! $

Usando el precario os._exit (en mi opinión, esto se incluye en "bloquear el intérprete"):

 >>> import os >>> try: ... os._exit(1) ... finally: ... print('finally!') ... $

Actualmente estoy ejecutando este código, para probar si finalmente se ejecutará después de la muerte por calor del universo:

 try: while True: sleep(1) finally: print('done')

Sin embargo, todavía estoy esperando el resultado, así que vuelva a consultar aquí más tarde.

over 4 years ago · Santiago Trujillo Denunciar

0

De acuerdo con la documentación de Python :

No importa lo que haya sucedido anteriormente, el bloque final se ejecuta una vez que se completa el bloque de código y se manejan las excepciones generadas. Incluso si hay un error en un controlador de excepciones o en el bloque else y se genera una nueva excepción, el código en el bloque final aún se ejecuta.

También se debe tener en cuenta que si hay varias instrucciones de devolución, incluida una en el bloque finalmente, la devolución del bloque finalmente es la única que se ejecutará.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda