如何正确处理异常?

时间:2011-05-23 23:25:49

标签: python variables exception-handling

我还不太明白如何在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 个答案:

答案 0 :(得分:4)

首先,如果你不介意例外,你可以让它通过:

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 :(得分:1)

您是否尝试过使用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"

“终于”将永远优秀,所以这就是你可以放置“完成”的东西。