使用Python+asyncio+aiohttp异步调用OpenAI API遇SSL错误求助
问题:异步调用OpenAI API出现SSL证书验证失败错误
我使用aiohttp和asyncio对OpenAI Completions API发起异步调用,通过DataFrame处理Door、Window、Table等查询请求,但每个请求均出现“SSL证书验证失败(证书已过期)”的错误。同步调用openai.completion.create可以正常执行,怀疑asyncio.gather与asyncio.create_task的使用存在问题,请求排查解决。
代码示例
# imports import pandas as pd # Make a dataframe import aiohttp # for making API calls concurrently import asyncio # for running API calls concurrently COMPLETIONS_MODEL = "text-davinci-003" request_url = "https://api.openai.com/v1/completions" request_header = {"Authorization": f"Bearer {api_key}"} # data prompt_list = ['Door', 'Window', 'Table'] init_context = " height if the room contains a door which is 8ft in height, a table 2ft in height and a window 6ft in height" # dataframe of list of questions q_dataframe = pd.DataFrame({"type": prompt_list}) async def process_question(question: str, context: str): query = "What is the " + question + context data = {'model': 'text-davinci-003', 'prompt': f'{query}'} try: async with aiohttp.ClientSession() as session: async with session.post(url=request_url, headers=request_header, json=data) as response: resp = await response.json() except Exception as e: print(f"Request failed {e}") async def process_questions(idf): results = await asyncio.gather(*[process_question(question, init_context) for question in idf['type']]) asyncio.create_task(process_questions(q_dataframe))
错误信息
Request failed Cannot connect to host api.openai.com:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1129)')]
排查与解决
1. 核心原因说明
SSL证书验证失败和asyncio.gather、asyncio.create_task的用法无关。同步调用正常说明你的API密钥、网络环境没问题,问题出在aiohttp依赖的系统根证书池未更新,或与官方OpenAI SDK使用的证书配置不一致,导致无法验证OpenAI的SSL证书。
2. 具体解决方案
方案一:更新系统根证书(推荐)
这是最安全的解决方式:- Windows:通过Windows Update完成系统证书更新
- macOS:导出OpenAI网站的根证书,执行
security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <证书文件路径>,或直接升级系统 - Linux(Debian/Ubuntu):执行
sudo apt update && sudo apt install --reinstall ca-certificates,其他发行版执行对应证书更新命令
方案二:为aiohttp指定可信证书
手动指定根证书文件,脱离系统证书池的依赖:import ssl # ... 保留原有导入与变量定义 ... async def process_question(question: str, context: str): query = "What is the " + question + context data = {'model': 'text-davinci-003', 'prompt': f'{query}'} try: # 创建自定义SSL上下文,指定可信证书文件路径 ssl_context = ssl.create_default_context(cafile="/path/to/your/ca-cert.pem") async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=ssl_context)) as session: async with session.post(url=request_url, headers=request_header, json=data) as response: resp = await response.json() return resp # 补充返回结果,让gather能收集到数据 except Exception as e: print(f"Request failed {e}")方案三:临时禁用证书验证(仅测试用,生产环境禁止)
若只是临时调试,可关闭SSL验证,但会带来明文传输的安全风险:async def process_question(question: str, context: str): query = "What is the " + question + context data = {'model': 'text-davinci-003', 'prompt': f'{query}'} try: # 禁用SSL验证 async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) as session: async with session.post(url=request_url, headers=request_header, json=data) as response: resp = await response.json() return resp except Exception as e: print(f"Request failed {e}")
3. 代码其他问题修复
process_question函数原本没有返回结果,asyncio.gather收集的results会全是None,需在请求成功后添加return resp- 最后执行逻辑中,
asyncio.create_task仅创建任务但不等待完成,脚本主线程结束后任务会被强制终止,应改为:asyncio.run(process_questions(q_dataframe))
内容的提问来源于stack exchange,提问作者Simon Palmer
相关产品推荐
相关产品推荐

