2010-03-04 3 views
3

J'ai besoin d'identifier qui soulève une exception pour gérer une meilleure erreur str, y at-il un moyen?Comment identifier quelle fonction appel déclencher une exception en Python?

oeil à mon exemple:

try: 
    os.mkdir('/valid_created_dir') 
    os.listdir('/invalid_path') 
except OSError, msg: 

    # here i want i way to identify who raise the exception 
    if is_mkdir_who_raise_an_exception: 
     do some things 

    if is_listdir_who_raise_an_exception: 
     do other things .. 

comment je peux gérer cela, en python?

Répondre

8

Si vous avez des tâches complètement séparées à exécuter en fonction de la fonction a échoué, car votre code semble montrer, puis séparer essayer/blocs exec, comme les réponses existantes suggèrent , peut être mieux (même si vous devrez probablement passer la deuxième partie si le premier a échoué). Si vous avez beaucoup de choses à faire dans les deux cas, et qu'une petite quantité de travail dépend de la fonction qui a échoué, la séparation peut créer beaucoup de duplication et de répétition, donc le formulaire que vous avez suggéré pourrait bien être préférable. Le module traceback dans la bibliothèque standard de Python peut aider dans ce cas:

import os, sys, traceback 

try: 
    os.mkdir('/valid_created_dir') 
    os.listdir('/invalid_path') 
except OSError, msg: 
    tb = sys.exc_info()[-1] 
    stk = traceback.extract_tb(tb, 1) 
    fname = stk[0][2] 
    print 'The failing function was', fname 

Bien sûr, au lieu du print que vous allez utiliser if contrôles pour décider exactement ce que le traitement à faire.

+0

+1 mais n'est pas stk [0] [3] qui retourne la fonction défaillante? – luc

+0

@luc, ce serait la source mais seulement si disponible; "" Une entrée de trace de pile "pré-traitée" est un quadruple '(nom de fichier, numéro de ligne, nom de la fonction, texte) 'représentant les informations habituellement imprimées pour une trace de pile Le texte est une chaîne avec les espaces avant et arrière effacés, si la source n'est pas disponible, elle est None." "" Comme vous voyez 'function_name' est à l'index 2 dans le tuple. –

+0

l'essayer/excepté, essayer/excepter la solution peut être mieux, mais dans mon cas je dois manipuler, quelle fonction soulevez l'exception, ainsi cette réponse est la meilleure pour moi! merci :) –

8

Enveloppez "essayer/attraper" chaque fonction individuellement.

try: 
    os.mkdir('/valid_created_dir') 
except Exception,e: 
    ## doing something, 
    ## quite probably skipping the next try statement 

try: 
    os.listdir('/invalid_path') 
except OSError, msg: 
    ## do something 

Cela aidera la lisibilité/compréhension de toute façon.

+0

Selon les détails, la seconde 'try ... except' pourrait éventuellement entrer dans un bloc' else: 'du premier. –

+1

Cela modifie légèrement la logique - si le 'mkdir' échoue parce que le répertoire existe déjà, il essaie de faire le' listdir' malgré tout. –

+0

Bien sûr, je n'ai pas conçu toute la solution, juste le principe. – jldupont

1

Que diriez-vous de la solution simple:

try: 
    os.mkdir('/valid_created_dir') 
except OSError, msg: 
    # it_is_mkdir_whow_raise_ane_xception: 
    do some things 

try: 
    os.listdir('/invalid_path') 
except OSError, msg:  
    # it_is_listdir_who_raise_ane_xception: 
    do other things .. 
0

Voici l'approche propre: joindre des informations complémentaires à l'exception où il se produit, puis l'utiliser dans un endroit unique:

import os, sys 
def func(): 
    try: 
     os.mkdir('/dir') 
    except OSError, e: 
     if e.errno != os.errno.EEXIST: 
      e.action = "creating directory" 
      raise 

    try: 
     os.listdir('/invalid_path') 
    except OSError, e: 
     e.action = "reading directory" 
     raise 

try: 
    func() 
except Exception, e: 
    if getattr(e, "action", None): 
     text = "Error %s: %s" % (e.action, e) 
    else: 
     text = str(e) 
    sys.exit(text) 

Dans la pratique, vous voulez créer des enveloppes pour des fonctions comme mkdir et listdir si vous voulez faire cela, plutôt que de disperser de petits blocs try/except partout dans votre code.

Normalement, je ne trouve pas ce niveau de détail dans les messages d'erreur si important (le message Python est généralement abondant), mais c'est une manière propre de le faire.

Questions connexes