Je veux réaliser quelque chose comme ceci:
def foo():
try:
raise IOError('Stuff ')
except:
raise
def bar(arg1):
try:
foo()
except Exception as e:
e.message = e.message + 'happens at %s' % arg1
raise
bar('arg1')
Traceback...
IOError('Stuff Happens at arg1')
Mais ce que j'obtiens c'est:
Traceback..
IOError('Stuff')
Des indices sur la façon d'y parvenir? Comment faire à la fois en Python 2 et 3?
message
attribut Exception, j'ai trouvé cette question SO, BaseException.message obsolète dans Python 2.6 , ce qui semble indiquer que son utilisation est maintenant déconseillée (et pourquoi elle n'est pas dans la documentation).Réponses:
Je le ferais comme ça, donc changer son type
foo()
ne nécessiterait pas de le changer égalementbar()
.Mise à jour 1
Voici une légère modification qui préserve le retraçage d'origine:
Mise à jour 2
Pour Python 3.x, le code de ma première mise à jour est syntaxiquement incorrect et l'idée d'avoir un
message
attribut sur aBaseException
été retirée lors d'un changement de PEP 352 le 16/05/2012 (ma première mise à jour a été publiée le 12/03/2012) . Donc actuellement, dans Python 3.5.2 de toute façon, vous devez faire quelque chose dans ce sens pour préserver le traçage et ne pas coder en dur le type d'exception dans functionbar()
. Notez également qu'il y aura la ligne:dans les messages de retraçage affichés.
Mise à jour 3
Un commentateur a demandé s'il y avait un moyen qui fonctionnerait à la fois dans Python 2 et 3. Bien que la réponse puisse sembler être "Non" en raison des différences de syntaxe, il existe un moyen de contourner cela en utilisant une fonction d'assistance comme
reraise()
dans l'six
add- sur le module. Donc, si vous préférez ne pas utiliser la bibliothèque pour une raison quelconque, vous trouverez ci-dessous une version autonome simplifiée.Notez aussi que puisque l'exception est relancée dans la
reraise()
fonction, cela apparaîtra dans tout ce que le retraçage est déclenché, mais le résultat final est ce que vous voulez.la source
__str__
, vous pouvez obtenir des résultats indésirables. Notez également que le deuxième argument est passé au constructeur donné par le premier argument, ce qui donne un peu de senstype(e)(type(e)(e.message)
. Troisièmement, e.message est obsolète au profit de e.args [0].Si vous êtes venu ici à la recherche d'une solution pour Python 3, le manuel dit:
Exemple:
Ce qui ressemble à ceci à la fin:
Transformer un totalement indéfinissable
TypeError
en un joli message avec des indices vers une solution sans gâcher l'exception d'origine.la source
e.args
, mais il s'agit d'un Tuple, il ne peut donc pas être modifié. Alors copiez-la d'abordargs
dans une liste, puis modifiez-la, puis recopiez-la sous forme de tuple:args = list(e.args)
args[0] = 'bar'
e.args = tuple(args)
En supposant que vous ne voulez pas ou ne pouvez pas modifier foo (), vous pouvez faire ceci:
C'est en effet la seule solution ici qui résout le problème dans Python 3 sans un message moche et déroutant "Lors de la gestion de l'exception ci-dessus, une autre exception s'est produite".
Dans le cas où la ligne de relance devrait être ajoutée à la trace de pile, écrire à la
raise e
place deraise
fera l'affaire.la source
e.args = ('mynewstr' + e.args[0],) + e.args[1:]
Je n'aime pas toutes les réponses données jusqu'à présent. Ils sont encore trop verbeux à mon humble avis. Dans la sortie de code et de message.
Tout ce que je veux, c'est le stacktrace pointant vers l'exception source, pas de truc d'exception entre les deux, donc pas de création de nouvelles exceptions, il suffit de re-surélever l'original avec tous les états de frame de pile pertinents , qui y ont conduit.
Steve Howard a donné une belle réponse que je veux étendre, non, réduire ... à python 3 uniquement.
La seule nouveauté est l' extension / décompression des paramètres qui le rend assez petit et assez facile à utiliser.
Essayez-le:
Cela vous donnera:
Un joli joli imprimé pourrait être quelque chose comme
la source
Une approche pratique que j'ai utilisée consiste à utiliser l'attribut de classe comme stockage pour les détails, car l'attribut de classe est accessible à la fois à partir de l'objet de classe et de l'instance de classe:
Puis dans votre code:
Et lors de la détection d'une erreur:
la source
Contrairement aux réponses précédentes, cela fonctionne face à des exceptions avec vraiment mauvais
__str__
. Il ne modifier le type cependant, afin de factoriser inutiles__str__
mises en œuvre.J'aimerais toujours trouver une amélioration supplémentaire qui ne modifie pas le type.
La trace et le type (nom) d'origine sont conservés.
la source
Je fournirai un extrait de code que j'utilise souvent chaque fois que je souhaite ajouter des informations supplémentaires à une exception. Je travaille à la fois en Python 2.7 et 3.6.
Le code ci-dessus donne la sortie suivante:
Je sais que cela s'écarte un peu de l'exemple fourni dans la question, mais j'espère néanmoins que quelqu'un le trouvera utile.
la source
Vous pouvez définir votre propre exception qui hérite d'une autre et créer son propre constructeur pour définir la valeur.
Par exemple:
la source
message
exception d'origine (mais pourrait être corrigée, je pense).Peut être
la source