Как правильно обрабатывать исключения? - PullRequest
4 голосов
/ 24 мая 2011

Я пока не совсем понимаю, как правильно использовать исключения в Python. Я хочу обработать данные, которым не могу полностью доверять (они подвержены изменениям, и если они изменятся, сценарий может сломаться). Допустим, я обрабатываю веб-страницу с помощью BeautifulSoup. Если автор веб-сайта вносит некоторые изменения в свой веб-сайт, некоторые заявления могут стать исключением. Давайте посмотрим на этот пример кода:

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

Теперь, если soup.find() не удастся из-за того, что владелец этого сайта изменит содержимое сайта и переименует ячейку Name в Names, будет сгенерировано исключение AttributeError: 'NoneType' object has no attribute 'parent'. Но я не против! Я ожидаю, что некоторые данные не будут доступны. Я просто хочу продолжить и использовать те переменные, которые у меня есть (конечно, будут некоторые данные, которые мне НУЖНЫ, и если они будут недоступны, я просто выйду.

Единственное решение, которое я придумал, это:

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

Есть ли лучший способ, или я должен просто продолжать делать попытку - за исключением каждого подобного утверждения? Это выглядит не очень хорошо.

РЕДАКТИРОВАТЬ: лучшее решение для меня будет следующим:

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

Это было бы здорово, но pass пропустит что-либо в try кодовом блоке, поэтому and few more things to complete никогда не будет напечатано. Если бы было что-то вроде pass, но оно просто проигнорировало бы ошибку и продолжило выполнение, было бы здорово.

Ответы [ 2 ]

4 голосов
/ 24 мая 2011

Во-первых, если вы не возражаете против исключения, вы можете просто пропустить его:

try:
    something()
except AttributeError:
    pass

но никогда не делайте это , поскольку оно позволит пройти все ошибки:

try:
    something()
except Exception:
    pass

Что касается вашего примера кода, возможно, он мог бы привести в порядок что-то вроде этого:

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])
1 голос
/ 24 мая 2011

Вы пытались использовать вместо этого оператор try / finally?

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

Пример из документов:

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

Итак, чтобы использовать ваш пример:

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"

«наконец-то» всегда будет оправданным, так что вы можете положить свои «завершающие» вещи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...