如何正确处理异常?
我还不太明白如何在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-except?这样看起来并不太好。
编辑:对我来说,最好的解决方案是这样的:
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 个回答
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"
“finally”部分总是会执行,所以你可以把“收尾工作”放在这里。
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])