python requests/urllib3连接池未捕获HTTP错误。

13 浏览
0 Comments

python requests/urllib3连接池未捕获HTTP错误。

使用连接池的python requests(urllib3)无法捕捉http错误。这是一个bug吗?还是我做错了什么?\n

#!/usr/bin/env python
import contextlib
import requests
import sys
connection_pool_size = 2
adapter = requests.adapters.HTTPAdapter(pool_connections=connection_pool_size,
                                        pool_maxsize=connection_pool_size)
r_session = requests.Session()
r_session.mount('http', adapter)
try:
    with contextlib.closing(r_session.get(sys.argv[1], timeout=30, allow_redirects=True)) as r:
        print 'success %r' % r
except requests.exceptions.HTTPError as e:
    print 'HTTPError %r' % e
except Exception as e:
    print 'Exception %r' % e

\n输出:\n

$ ./test.py https://github.com
success 
$ ./test.py https://github.com/sithlordyoyoma
success 

\n我本来期望得到HTTPError。我做错了什么吗?\n我从这个线程中获得了contextlib的关闭方法should I call close() after urllib.urlopen()?。这是根据Alex Martelli的建议。\n实际上,不使用连接的requests也显示了这种行为\n

#!/usr/bin/env python
import contextlib
import requests
import sys
try:
    with contextlib.closing(requests.get(sys.argv[1], timeout=30, allow_redirects=True)) as r:
        print 'success %r' % r
except requests.exceptions.HTTPError as e:
    print 'HTTPError %r' % e
except Exception as e:
    print 'Exception %r' % e

\n输出:\n

$ ./test.py https://github.com
success 
$ ./test.py https://github.com/sithlordyoyoma
success 

\nurllib2可以正确处理这个问题\n

#!/usr/bin/env python
import contextlib
import urllib2
import sys
try:
    with contextlib.closing(urllib2.urlopen(sys.argv[1], timeout=30)) as r:
        print 'success %r' % r
except urllib2.HTTPError as e:
    print 'HTTPError %r' % e
except Exception as e:
    print 'Exception %r' % e

\n输出:\n

$ ./test.py https://github.com
success >
$ ./test.py https://github.com/sithlordyoyoma
HTTPError HTTPError()

0
0 Comments

无论是否使用连接池,requests.post(以及其他HTTP方法)在遇到404错误时都不会引发HTTPError异常。要引发HTTPError异常,需要调用.raise_for_status()方法,就像下面的示例所演示的那样:

#!/usr/bin/env python
import requests
r = requests.post(
    'https://github.com/sithlordyoyoma',
    timeout=30,
    allow_redirects=True
)
print 'success %r' % r
r.raise_for_status()

唉,看了文档,明白了。我原本期望的行为类似于urllib2。这就是困惑的根源。 docs.python-requests.org/en/latest/api/…

问题的原因是使用requests.post方法时,无论是否使用连接池,在遇到404错误时都不会引发HTTPError异常,这与urllib2的行为不同,导致了混淆。

解决方法是,在使用requests.post方法后调用.raise_for_status()方法,以便在遇到HTTP错误时引发HTTPError异常。

这篇文章指出了使用requests.post方法时的一个问题:无论是否使用连接池,在遇到404错误时都不会引发HTTPError异常。然后提供了解决方法,即在调用requests.post方法后调用.raise_for_status()方法。

0