异步aiohttp请求失败,但同步请求成功

Tim*_*Tim 6 asynchronous python-3.x python-asyncio aiohttp

使用以下代码,我Cannot connect to host ...:443 ssl:True在使用异步时获得aiohttp.当我使用同步时requests,它会成功.

whitehouse.gov链接失败,但google.com成功的两个异步和同步情况.

出了什么问题?这是在FreeBSD8上的python 3.4.2,aiohttp 0.14.4,请求2.5.3

import asyncio
import aiohttp
import requests

urls = [
    'http://www.whitehouse.gov/cea/', 
    'http://www.whitehouse.gov/omb', 
    'http://www.google.com']


def test_sync():
    for url in urls:
        r = requests.get(url)
        print(r.status_code)


def test_async():
    for url in urls:
        try:
            r = yield from aiohttp.request('get', url)
        except aiohttp.errors.ClientOSError as e:
            print('bad eternal link %s: %s' % (url, e))
        else:
            print(r.status)


if __name__ == '__main__':
    print('async')
    asyncio.get_event_loop().run_until_complete(test_async())
    print('sync')
    test_sync()
Run Code Online (Sandbox Code Playgroud)

这个输出是:

async
bad eternal link http://www.whitehouse.gov/cea: Cannot connect to host www.whitehouse.gov:443 ssl:True
bad eternal link http://www.whitehouse.gov/omb: Cannot connect to host www.whitehouse.gov:443 ssl:True
200
sync
200
200
200
Run Code Online (Sandbox Code Playgroud)

And*_*lov 9

我怀疑您的机器上的证书验证链已损坏.正如@dano所提到的,在Ubuntu上一切正常.

无论如何,您可以通过创建自定义Connector实例来禁用ssl验证:

import asyncio
import aiohttp

urls = [
    'http://www.whitehouse.gov/cea/',
    'http://www.whitehouse.gov/omb',
    'http://www.google.com']


def test_async():
    connector = aiohttp.TCPConnector(verify_ssl=False)
    for url in urls:
        try:
            r = yield from aiohttp.request('get', url, connector=connector)
        except aiohttp.errors.ClientOSError as e:
            print('bad eternal link %s: %s' % (url, e))
        else:
            print(r.status)


if __name__ == '__main__':
    print('async')
    asyncio.get_event_loop().run_until_complete(test_async())
Run Code Online (Sandbox Code Playgroud)

BTW,requests库附带自己的证书包.也许我们需要为aiohttp做同样的事情?

UPD.另见https://github.com/aio-libs/aiohttp/issues/341

  • 正是问题所在,谢谢。如果我没有巧妙地隐藏在 try/ except 后面,我会得到更多有用的信息: ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败 (_ssl.c:600)。您关闭验证的解决方案就是诀窍。 (2认同)
  • 在“TCPConnector”中设置“ssl=False”时,我通常会收到同样的异常。 (2认同)

Le *_*bou 6

我在旧的 Linux 服务器上遇到了同样的问题,该服务器具有过期的 CA 根证书,并加载certifi CA 证书捆绑包修复了SSLContext该问题。

import aiohttp
import ssl
import certifi

ssl_context = ssl.create_default_context(cafile=certifi.where())
async with aiohttp.ClientSession() as session:
    async with session.get('https://some.foo/bar/', ssl=ssl_context) as response:
        print(await response.text())
Run Code Online (Sandbox Code Playgroud)