Python 3.x 异步aiohttp请求失败,但同步请求成功
使用以下代码,当我使用异步Python 3.x 异步aiohttp请求失败,但同步请求成功,python-3.x,asynchronous,python-asyncio,aiohttp,Python 3.x,Asynchronous,Python Asyncio,Aiohttp,使用以下代码,当我使用异步aiohttp时,我得到无法连接到主机…:443 ssl:True。当我使用同步请求时,它会成功 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/c
aiohttp
时,我得到无法连接到主机…:443 ssl:True
。当我使用同步请求时,它会成功
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()
此操作的输出为:
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
我怀疑您的机器上的证书验证链已断开。
正如@dano所提到的,在Ubuntu上一切都正常
无论如何,您可以通过创建自定义连接器
实例来禁用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())
顺便说一句,请求
库附带有自己的证书包。也许我们也需要为aiohttp做同样的事情
UPD。另请参见不要使用此Answare,因为它可能等同于禁用证书检查。
正如Le Hibou在评论中指出的,ssl.Purpose.CLIENT\u AUTH
用于在服务器端验证客户端
此值表示上下文可用于验证Web客户端(因此,它将用于创建服务器端套接字)
查看create\u default\u context()
的代码可以看出,在这种情况下,证书检查可能被禁用,或者至少是可选的
我收到了相同的错误消息(在Windows上),并通过以下方法解决了此问题:
导入aiohttp
导入ssl
client=aiohttp.ClientSession()
client.post(
'https://some.foo/bar/',
json={“foo”:“bar},
ssl=ssl.create\u default\u context(purpose=ssl.purpose.CLIENT\u AUTH))
这是使用的ssl
参数设置与默认ssl上下文不同的ssl上下文。默认值为
问题在于ssl.create\u default\u context()
的默认值是:
ssl.create\u default\u context(purpose=purpose.SERVER\u AUTH,cafile=None,capath=None,cadata=None)
在客户端验证服务器证书时,Purpose.SERVER\u AUTH
似乎不起作用。作为客户端进行验证时,请改用Purpose.CLIENT\u AUTH
。我在一台旧Linux服务器上遇到了同样的问题,该服务器上的CA根证书已过期,在SSLContext
中加载CA证书捆绑包修复了该问题
导入aiohttp
导入ssl
进口证书
ssl\u context=ssl.create\u default\u context(cafile=certifi.where())
与aiohttp.ClientSession()作为会话异步:
与session.get()异步https://some.foo/bar/,ssl=ssl_上下文)作为响应:
打印(等待响应。text())
这对我很有用:
if sys.version_info[0] == 3 and sys.version_info[1] >= 8 and sys.platform.startswith('win'):
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
这不会在Ubuntu机器上为我复制,因为它的价值。正是问题所在,谢谢。如果我没有巧妙地隐藏在try/except后面,我会得到更多有用的信息:ssl.SSLError:[ssl:CERTIFICATE\u VERIFY\u FAILED]CERTIFICATE VERIFY FAILED(\u ssl.c:600)。您关闭验证的解决方案就是诀窍。@Tim,异常的完整信息指向异常链中的错误源,不是吗?是的--没有try/except,所有正确的信息都会显示出来。我用try/except屏蔽了错误,只得到了我的异常文本+“无法连接到www.whitehouse.gov:443”。如果我建立了裸连接,我会看到完整的回溯——从ssl.SSLError开始,以aiohttp.errors.clientorror结束。经验教训(在开发代码时不要掩盖异常!)在TCPConnector
中设置ssl=False
时,我通常会收到相同的异常。这让人困惑。。。根据,Purpose.CLIENT\u AUTH
用于创建服务器端套接字。很好,我忽略了这一点。查看create\u default\u context()
的源代码,似乎可以使用ssl.Purpose.CLIENT\u AUTH
禁用或选择证书检查。