2011-05-23 5 views
4

Je ne comprends pas encore comment utiliser correctement les exceptions en Python. Je veux traiter les données auxquelles je ne peux pas faire entièrement confiance (elles sont susceptibles de changer, et si elles changent, le script peut se casser). Disons que je traite une page Web en utilisant BeautifulSoup. Si l'auteur du site Web apporte des modifications à son site Web, certaines déclarations peuvent susciter des exceptions. Regardons cet exemple de code:Comment gérer les exceptions correctement?

data = urllib2.urlopen('http://example.com/somedocument.php').read() 
soup = BeautifulSoup(data, convertEntities="html") 

name = soup.find('td', text=re.compile(r'^Name$')).parent.nextSibling.string 

print name 

Maintenant, si soup.find() échouent parce que le propriétaire de ce site Web va changer le contenu du site et renommer la cellule Name-Names, une exception AttributeError: 'NoneType' object has no attribute 'parent' sera soulevée. Mais ça ne me dérange pas! Je m'attends à ce que certaines données ne soient pas disponibles. Je veux juste continuer et utiliser les variables dont je dispose (bien sûr il y aura des données que je besoin, et si elles ne sont pas disponibles je me contenterai de sortie

La seule solution que je suis venu avec est:.

try: name = soup.find('td', text=re.compile(r'^Name$')).parent.nextSibling.string 
except AttributeError: name = False 
try: email = soup.find('td', text=re.compile(r'^Email$')).parent.nextSibling.string 
except AttributeError: email = False 
try: phone = soup.find('td', text=re.compile(r'^Phone$')).parent.nextSibling.string 
except AttributeError: phone = False 

if name: print name 
if email: print email 
if phone: print phone 

y at-il une meilleure façon, ou devrais-je regarder simplement continuer à faire essayer, sauf pour chaque déclaration similaire Il n'a pas très agréable du tout

EDIT:. la meilleure solution pour moi serait comme ceci:

try: 
    print 'do some stuff here that may throw and exception' 
    print non_existant_variable_that_throws_an_exception_here 
    print 'and few more things to complete' 
except: 
    pass 

Ce serait génial, mais pass passera n'importe quoi dans le bloc de code try, donc and few more things to complete ne sera jamais imprimé. S'il y avait quelque chose comme passer, mais il serait juste ignorer l'erreur et continuer à exécuter, ce serait génial.

+0

Utilisez 'finally'. http://docs.python.org/tutorial/errors.html#defining-clean-up-actions – sdolan

+0

"pass passera n'importe quoi dans le bloc de code try". Correct. Pourquoi mettre autant d'instructions dans le bloc 'try:'? –

Répondre

4

Tout d'abord, si vous ne me dérange pas l'exception, vous pouvez simplement laisser passer:

try: 
    something() 
except AttributeError: 
    pass 

mais jamais faire ce car il est laissera toutes les erreurs passent:

try: 
    something() 
except Exception: 
    pass 

En ce qui concerne votre exemple de code, peut-être qu'il pourrait être rangé avec quelque chose comme ceci:

myDict = {} 

for item in ["Name", "Email", "Phone"]: 
    try: 
     myDict[item] = soup.find('td', text=re.compile(r'^%s$' % item)).parent.nextSibling.string 
    except Attribute 
     myDict[item] = "Not found" 

for item in ["Name", "Email", "Phone"]: 
    print "%s: %s" % (item, myDict[item]) 
+0

Merci pour votre suggestion première suggestion. Si je ne me trompe pas, il devrait être «sauf» au lieu de «attraper». Mais de toute façon, regardez ma question éditée. Quant à la deuxième suggestion, je comprends que mon exemple aurait du sens d'utiliser dict et de faire quelque chose comme ce que vous avez suggéré.Mais ce n'était qu'un exemple, je ne pense pas que ça marcherait très bien dans mon cas. Je préférerais simplement vérifier si la variable est disponible et l'utiliser, sinon, continuer. – Gargauth

+0

Oh oui, whoops j'étais pressé je suppose. :-( – nakedfanatic

1

Avez-vous essayé d'utiliser une instruction try/finally à la place?

http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

Exemple des docs:

>>> def divide(x, y): 
...  try: 
...   result = x/y 
...  except ZeroDivisionError: 
...   print "division by zero!" 
...  else: 
...   print "result is", result 
...  finally: 
...   print "executing finally clause" 

Donc, pour utiliser votre exemple:

try: 
    do_some_stuff_here_that_may_throw_an_exception() 
except someError: 
    print "That didn't work!" 
else: 
    print variable_that_we_know_didnt_throw_an_exception_here 
finally: 
    print "finishing up stuff" 

"enfin" aura toujours Excecute, donc c'est où vous pouvez mettre votre " finir des trucs.

Questions connexes