python-binance WebSocket报SSL证书验证失败错误如何处理
问题描述
运行基于python-binance库编写的、用ThreadedWebsocketManager监听BTCUSDT行情的简易交易脚本时,线程抛出SSL证书验证异常,核心报错为ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain,最终触发aiohttp.client_exceptions.ClientConnectorCertificateError,提示无法连接api.binance.com:443。
涉及的原脚本代码如下:
from binance.client import Client from binance import ThreadedWebsocketManager import pandas as pd my_api = "" my_secret = "" client = Client(api_key=my_api, api_secret=my_secret, tld="com", testnet=True) twm = ThreadedWebsocketManager(api_key=my_api, api_secret=my_secret) twm.start() def simple_bot(msg): ''' define how to process incoming WebSocket messages ''' time = pd.to_datetime(msg["E"], unit="ms") price = float(msg["c"]) print("Time: {} | Price: {}".format(time, price)) if int(price) % 10 == 0: order = client.create_order(symbol="BTCUSDT", side="BUY", type="MARKET", quantity=0.1) print("\n" + 50 * "-") print("Buy {} BTC for {} USDT".format(order["executedQty"], order["cummulativeQuoteQty"])) print(50 * "-" + "\n") twm.stop() twm.start_symbol_ticker_socket(callback=simple_bot, symbol="BTCUSDT")
故障诱因
- 本地网络存在HTTPS拦截:包括公司内网代理、开启HTTPS解密的代理工具、杀毒软件的HTTPS流量扫描功能,这类中间节点会替换Binance接口的官方SSL证书,导致Python默认证书链校验失败
- Python环境的CA根证书库版本过旧,无法识别Binance当前使用的合法SSL证书
- 代码配置不匹配:初始化
ThreadedWebsocketManager时未开启testnet=True参数,默认连接主网websocket接口,和Client的测试网配置不一致,且主网地址在当前网络下被证书拦截
解决方案
按优先级从高到低尝试:
- 修正代码配置参数
初始化ThreadedWebsocketManager时同步开启测试网配置,和Client参数保持一致,修改对应代码为:# twm初始化时增加testnet=True参数 twm = ThreadedWebsocketManager(api_key=my_api, api_secret=my_secret, testnet=True) - 更新本地CA证书库
执行终端命令更新Python依赖的证书包:
如果使用MacOS系统,额外执行对应Python版本的证书安装脚本,将路径中的pip install --upgrade certifi3.x替换为本地实际安装的Python版本号:open /Applications/Python\ 3.x/Install\ Certificates.command - 排查网络拦截
临时关闭杀毒软件的网页防护/HTTPS扫描功能、退出带HTTPS解密规则的代理工具,切换到无特殊拦截的网络环境重试;如果使用公司内网,联系网络管理员放开Binance接口域名的SSL拦截规则。 - 临时关闭SSL校验(仅测试环境可用,生产环境严禁使用,存在中间人攻击风险)
如果上述方案都无效,可在测试阶段临时关闭SSL校验,先导入ssl模块,再修改Client和twm初始化代码:import ssl # Client初始化增加verify=False参数 client = Client(api_key=my_api, api_secret=my_secret, tld="com", testnet=True, verify=False) # 构造不校验证书的SSL上下文传入twm ssl_context = ssl.create_default_context() ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE twm = ThreadedWebsocketManager(api_key=my_api, api_secret=my_secret, testnet=True, ssl_context=ssl_context)
内容的提问来源于stack exchange,提问作者Kyungyun Lee
相关产品推荐
相关产品推荐

