最近在玩一些开源项目的时候,编译脚本需要使用urllib2去一些https网站去拉取一些东西,结果遇到以下问题:
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 429, in open
response = self._open(req, data)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 447, in _open
'_open', req)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 407, in _call_chain
result = func(*args)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1241, in https_open
context=self._context)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1198, in do_open
raise URLError(err)
urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)>
因为本地机器安装有anaconda的python3和默认的python2,而系统默认的python是3.x版本的。开始的时候走了弯路,一直怀疑是着python3中的openssl版本不对,尝试修改用处不大。再后来结合代码和日志看出来这个是python2的问题。
再进行搜索发现这个问题是从python2.7.9开始引入的,是为了防止中间人攻击,在访问https的时候会检查服务器证书签名是否是CA的可信任根证书。报错就是发生在这个过程。
解决方法有两种:
- 比较快但是不太安全的方法
export PYTHONHTTPSVERIFY=0
python your_script
或者PYTHONHTTPSVERIFY=0 python your_script
- 在自己脚本中加入处理:
import os, ssl
if (not os.environ.get('PYTHONHTTPSVERIFY', '') and
getattr(ssl, '_create_unverified_context', None)):
ssl._create_default_https_context = ssl._create_unverified_context
参考:
https://www.jianshu.com/p/d3b60e42fc02
https://moreless.medium.com/how-to-fix-python-ssl-certificate-verify-failed-97772d9dd14c