2.14.1 基本语法

当我们在浏览器里尝试访问不存在的网址时,浏览器会报错,告诉我们地址不存在。当我们用Python代码尝试访问不存在的网址时,代码也会报错。

用requests模块,成功访问bing.com:


>>> import requests
>>> requests.get('http://www.bing.com')
<Response [200]>

访问一个不存在的网址http://www.bingbingbangbang.com,有异常发生:


>>> requests.get('http://www.bingbingbangbang.com')
Traceback (most recent call last):
......
    r = adapter.send(request, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-
      packages/requests/adapters.py", line 508, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='www.
    bingbingbangbang.com', port=80): Max retries exceeded with url: / (Caused by 
    NewConnectionError('<urllib3.connection.HTTPConnection object at 
    0x1018a1128>: Failed to establish a new connection: [Errno 8] nodename nor 
    servname provided, or not known',))

这只是截取后的片段,原始的错误信息更冗长。在很多应用场合,我们并不想看到这么具体的错误信息,更不想让程序就此崩溃,我们只是想知道网址是否可以正确访问。比如,hao123.com网站页面聚合了大量的网址链接,如果想知道其中是否有异常链接,我们可以逐一访问检测,但是如果有访问异常发生,我们不希望程序崩溃,不希望后续的检测被影响。

我们来尝试用异常处理来重构代码,把可能出错的代码放在try代码块中,把错误处理的逻辑放在except代码块中,异常发生的时候会被捕获,程序执行会立刻转到except代码块中。


try:
  do_something()
except:
  print("Something bad happened")

用异常处理来重构网页的访问。


import requests

urls = [
    'http://www.bing.com',
    'http://www.bingbingbangbang.com',
    'http://www.yahoo.com'
]

for url in urls:
    try:
        requests.get(url)
        print('SUCCESS:', url)
    except:
        print('FAILED: ', url)

执行结果如下:


SUCCESS: http://www.bing.com
FAILED:  http://www.bingbingbangbang.com
SUCCESS: http://www.yahoo.com

通常情况下,我们会用except...as捕获异常对象,获取具体的错误信息,以便后续排查分析。


variables = ['11', '-12', '33.3', '二十一']

for variable in variables:
    try:
        int_variable = int(variable)
    except Exception as err:
        print('Failed in casting "{}" to integer'.format(variable))
        print(err)
    print()

执行结果如下:


Failed in casting "33.3" to integer
invalid literal for int() with base 10: '33.3'

Failed in casting "二十一" to integer
invalid literal for int() with base 10: '二十一'

当异常发生的时候,try代码块里出错点以后的代码都不会被执行,程序执行逻辑会转到except代码块里面去。


try:
    print('aa')
    print('bb')
    c = 12 + '21'
    print('dd')
except:
    print('error happened!!!')

执行结果如下:


aa
bb
error happened!!!

我们可以用finally来指明try/except之后执行的逻辑,不管有没有异常发生,finally中的代码都会被执行。比如,在建立了数据库连接之后执行查询操作,不管查询操作是不是有异常发生,我们都希望在查询操作结束之后把数据库连接关掉,这种情况可以在finally代码块中执行关闭数据库连接的操作。


try:
    print('aa')
    print('bb')
    c = 12 + '21'
    print('dd')
except:
    print('error happened!')
finally:
    print('It is over anyway')

执行结果如下:


aa
bb
error happened!
It is over anyway