Python通过SSL调用API时响应不完整,JSON解码失败求助
问题分析与解决
你的核心错误是误解了TCP socket的recv()行为:TCP是面向流的协议,数据会被拆分成多个TCP段发送,单次recv()只能返回当前内核缓冲区中可用的部分数据——哪怕你设置了超大的缓冲区,也无法保证一次性拿到完整的响应。你看到的13680字符就是单次recv()能获取的最大可用数据量,剩余数据还在传输或等待接收。
正确的处理方式
必须循环接收数据,直到确认拿到了完整的响应。具体实现可以根据API的通信约定选择以下方案:
方案1:基于约定的结束符(如\n)
如果API响应和你的请求一样,以换行符\n作为结束标记,可以循环接收直到读取到该符号:
request = json.dumps(request) + "\n" connection.sendall(request.encode()) response_data = b"" while True: # 使用固定合理的缓冲区大小(如4096)即可,无需与n_data绑定 chunk = connection.recv(4096) if not chunk: # 连接被对方关闭,无更多数据 break response_data += chunk # 检查当前块是否包含结束符,包含则停止接收 if b"\n" in chunk: break # 去掉末尾的换行符后解码解析 response = response_data.decode().strip() print(len(response)) response = json.loads(response)
方案2:基于JSON解析成功的判断
如果没有明确的结束符,可以尝试循环接收直到JSON能成功解析(不完整的JSON会抛出JSONDecodeError):
import json request = json.dumps(request) + "\n" connection.sendall(request.encode()) response_data = b"" while True: chunk = connection.recv(4096) if not chunk: raise ConnectionError("API连接提前关闭,未收到完整响应") response_data += chunk try: # 尝试解码并解析JSON response_str = response_data.decode() response = json.loads(response_str) # 解析成功,说明数据完整,跳出循环 break except json.JSONDecodeError: # 解析失败,继续接收更多数据 continue print(len(response_str))
额外提示
- 不要将
recv()的缓冲区大小与请求的n_data绑定,固定使用4096或8192这类通用大小即可,过大的缓冲区不会提升接收完整性,只会占用更多内存。 - SSL socket的接收逻辑和普通TCP socket完全一致,流式协议的特性不会因SSL加密而改变。
内容的提问来源于stack exchange,提问作者Francesco Battisti
相关产品推荐
相关产品推荐

