2017-09-22 5 views
1

Les fonctions a() et b() peuvent générer une exception. Ce code ne traite pas tout exception est de lancer pendant l'affectation "UnboundLocalError: Variable locale 'x' référencé avant cession" code:Comment faire pour ommit UnboundLocalError: Variable locale '' référencée avant l'affectation lorsque l'exception a été levée?

def foo(): 
    try: 
     x = a('test') 
     b(x, 'test2') 
    except Exception as ex: 
     raise Exception('Message error: ' + str(x) + " " + str(ex)) #here could be UnboundLocalError: Local variable 'x' referenced before assignment 

Ma solution est:

def foo(): 
    try: 
     x = a('test') 
     try: 
      b(x, 'test2') 
     except Exception as ex: 
      raise Exception('Message error: ' + str(x) + " " + str(ex))   
    except Exception as ex: 
     raise Exception('Message error: ' + str(ex)) 

Est-il possible de le faire c'est plus compliqué, élégant? Maintenant, je suis obligé d'utiliser double try sauf template.

+0

Pourquoi avez-vous besoin de faire référence 'x' dans le message d'exception en premier lieu? – roganjosh

+0

En outre, ce n'est pas une bonne idée d'avoir deux fonctions regroupées dans une exception fourre-tout comme vous vouliez dans le premier bloc (ou utiliser une couverture 'except 'en général). Est-ce que 'x = a ('test')' échoue ou 'b (x, 'test2')'? Actuellement votre façon de déchiffrer cela est en soulevant encore une autre exception qui n'est pas prise. – roganjosh

Répondre

0

Ceci est probablement une façon que vous pouvez le faire:

try: 
    x = a('test') 
    b(x, 'test2') 
except Exception as ex: 
    if not 'x' in locals(): 
     x = 'undefined' 
    raise Exception('Message error: ' + str(x) + " " + str(ex)) 

Personnellement, je pense attrapant les deux exceptions essayer séparée/sauf blocs est plus élégant, car il montre le lecteur qu'un() n'a pas réussi à complet et un UnboundLocalError qui autorise pas masque la vraie question:

try: 
    x = a('test') 
except Exception as ex: 
    raise Exception('oh no, a() failed') 
try: 
    b(x, 'test2') 
except Exception as ex: 
    raise Exception('oops, b() failed') 

Voici quelques documentation sur locals(): https://docs.python.org/3/library/functions.html#locals

+1

Mais la logique du flux n'a pas de sens. Si 'x = a ('test')' échoue alors 'b (x, 'test2')' est clairement impossible, alors pourquoi l'avoir dans le même 'try'? Juste avoir deux 'try' /' except', un pour chacun, et l'ont fait avec. Il n'y a rien d'extraordinaire ou de pythonique à propos des exceptions d'imbrication comme celle-ci ... – roganjosh

+1

Vous avez raison, je n'étais pas clair dans ma réponse. C'est ce que je voulais dire par "attraper les deux exceptions". Bien que, UnboundLocalError ne serait même pas déclenché. Edité avec une meilleure stratégie. – Mario

+1

Beaucoup mieux :) A l'air moins impressionnant que niché mais fait beaucoup plus de sens! – roganjosh

0

Vous pouvez utiliser la clause de else[Python]: The try statement:

def foo(): 
    try: 
     x = a("test") 
    except Exception as ex: 
     raise Exception("Message error (a): " + str(ex)) 
    else: 
     try: 
      b(x, "test2") 
     except Exception as ex: 
      raise Exception("Message error (b): " + str(x) + " " + str(ex))