Cuando se usa PyCharm IDE, el uso de except:
sin un tipo de excepción activa un recordatorio del IDE de que esta cláusula de excepción es Too broad
.
¿Debería ignorar este consejo? ¿O es Pythonic especificar siempre el tipo de excepción?
Cuando se usa PyCharm IDE, el uso de except:
sin un tipo de excepción activa un recordatorio del IDE de que esta cláusula de excepción es Too broad
.
¿Debería ignorar este consejo? ¿O es Pythonic especificar siempre el tipo de excepción?
Respuestas:
Casi siempre es mejor especificar un tipo de excepción explícita. Si usa una except:
cláusula simple , puede terminar detectando excepciones distintas de las que espera detectar; esto puede ocultar errores o dificultar la depuración de programas cuando no están haciendo lo que espera.
Por ejemplo, si está insertando una fila en una base de datos, es posible que desee detectar una excepción que indique que la fila ya existe, de modo que pueda realizar una actualización.
try:
insert(connection, data)
except:
update(connection, data)
Si especifica un bare except:
, también detectará un error de socket que indica que el servidor de la base de datos se ha caído. Es mejor detectar solo las excepciones que sepa cómo manejar; a menudo es mejor que el programa falle en el punto de la excepción que continuar pero comportarse de maneras extrañas e inesperadas.
Un caso en el que es posible que desee utilizar un except:
programa básico es en el nivel superior de un programa que debe estar siempre en ejecución, como un servidor de red. Pero entonces, debe tener mucho cuidado al registrar las excepciones, de lo contrario, será imposible averiguar qué está fallando. Básicamente, solo debería haber como máximo un lugar en un programa que haga esto.
Un corolario de todo esto es que su código nunca debería funcionar raise Exception('some message')
porque obliga a usar el código del cliente except:
(o except Exception:
que es casi tan malo). Debe definir una excepción específica para el problema que desea señalar (tal vez heredando de alguna subclase de excepción incorporada como ValueError
o TypeError
). O debería generar una excepción incorporada específica. Esto permite a los usuarios de su código tener cuidado al detectar solo las excepciones que desean manejar.
except:
también captura (entre muchas otras cosas) NameError
y AttributeError
, por lo tanto, si escribe mal algo en el try
bloque (por ejemplo, su función "insertar" se llama en realidad insert_one
porque alguien no valora la coherencia tanto como debería), siempre lo intenta en silencio update()
.
main()
)?
except Exception:
atrapará NameError
y AttributeError
también. Lo que hace que el desnudo sea except:
tan malo es que captura cosas que no tienen por qué ser capturadas, por ejemplo, SystemExit
(se genera cuando llamas exit
o sys.exit
, y ahora has evitado una salida prevista) y KeyboardInterrupt
(nuevamente, si el usuario golpea Ctrl-C
, probablemente no quieras para seguir corriendo solo para fastidiarlos). Solo el último tiene algún sentido real de atrapar, y debe capturarse explícitamente. Al menos except Exception:
deja que esos dos se propaguen normalmente.
No debe ignorar los consejos que le da el intérprete.
De la Guía de estilo de PEP-8 para Python:
Cuando detecte excepciones, mencione excepciones específicas siempre que sea posible en lugar de usar una cláusula except: desnuda.
Por ejemplo, use:
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
Una simple cláusula except: capturará las excepciones SystemSalir y KeyboardInterrupt, lo que hará más difícil interrumpir un programa con Control-C, y puede ocultar otros problemas. Si desea capturar todas las excepciones que señalan errores de programa, use except Exception: (bare except es equivalente a except BaseException :).
Una buena regla general es limitar el uso de cláusulas "excepto" desnudas a dos casos:
Si el manejador de excepciones imprimirá o registrará el rastreo; al menos el usuario será consciente de que se ha producido un error. Si el código necesita hacer algún trabajo de limpieza, pero luego permite que la excepción se propague hacia arriba con raise. intentar ... finalmente puede ser una mejor manera de manejar este caso.
No específico para Python esto.
El objetivo de las excepciones es abordar el problema lo más cerca posible de donde se originó.
Por lo tanto, mantiene el código que, en circunstancias excepcionales, podría desencadenar el problema y la resolución "al lado".
El caso es que no puede conocer todas las excepciones que podría generar un fragmento de código. Todo lo que puede saber es que si se trata de una excepción de archivo no encontrado, entonces puede interceptarlo y pedirle al usuario que obtenga uno que lo haga o cancele la función.
Si intenta atrapar eso, entonces no importa qué problema haya en su rutina de archivos (solo lectura, permisos, UAC, no realmente un pdf, etc.), todos ingresarán a su archivo no encontrado, y su usuario está gritando "pero está ahí, este código es una mierda"
Ahora bien, hay un par de situaciones en las que puede captar todo, pero deben elegirse conscientemente.
Se capturan, deshacen alguna acción local (como crear o bloquear un recurso, (abrir un archivo en el disco para escribir, por ejemplo), luego lanzar la excepción nuevamente, para que se trate en un nivel superior)
El otro tú es que no te importa por qué salió mal. Impresión, por ejemplo. Es posible que tenga una trampa en general, como decir Hay algún problema con su impresora, por favor, resuélvalo y no elimine la aplicación por eso. Un vano similar si su código ejecutara una serie de tareas separadas usando algún tipo de horario, no querría que todo se muera, porque una de las tareas falló.
Nota Si hace lo anterior, no puedo recomendar algún tipo de registro de excepción, por ejemplo, intente capturar el final del registro, lo suficiente.
También atraparás, por ejemplo, Control-C con eso, así que no lo hagas a menos que lo "tires" de nuevo. Sin embargo, en ese caso debería utilizar "finalmente".
Siempre especifique el tipo de excepción, hay muchos tipos que no quieren ponerse al día, como SyntaxError
, KeyboardInterrupt
, MemoryError
etc.
except Exception:
evitar los tipos anteriores que no queremos atrapar?
except Exception
está bien.
except Exception
atrapa SyntaxError
y MemoryError
porque es su clase base. KeyboardInterrupt
, SystemExit
(planteados por sys.exit()
) no se detectan (son subclases de BaseException inmediatas)
Aquí están los lugares donde uso excepto sin tipo
Ese es el uso principal en mi código para excepciones no verificadas.
Siempre agrego esto, para que el código de producción no derrame rastros de pila
Tengo dos formas de hacerlo:
Lo prefiero de esta manera, me resulta más fácil detectar qué excepciones deberían haberse detectado correctamente: "veo" mejor el problema cuando un nivel superior registra una excepción de nivel inferior
Algunos compañeros de trabajo prefieren esta forma, ya que mantiene excepciones de nivel inferior en funciones de nivel inferior, a las que "pertenecen".
Prueba esto:
try:
#code
except ValueError:
pass
Obtuve la respuesta de este enlace, si alguien más se encuentra con este problema , compruébelo