Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

336
Views
¿'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 answers
Answer question

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 información.

    Otras formas en que un generador o una corrutina podrían no ejecutarse hasta la conclusión incluyen si el objeto nunca se GC'ed (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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!