Python虚拟环境与系统环境中requests模块行为差异求助
虚拟环境中requests模块SSL证书验证失败问题
问题背景
终于意识到虚拟环境对项目的优势——将所有模块及版本封装在项目内,能避免使用旧脚本/项目时频繁遇到的依赖冲突问题。但实际操作中出现异常:虚拟环境中的requests模块与系统环境表现不一致,运行脚本时抛出SSL证书验证错误,而系统环境运行完全正常。
虚拟环境初始化步骤
:: SETTING UP A VIRTUAL ENVIRONMENT (PYTHON 2.7) AND INSTALLING MODULES D:\Projects\MyProject>"C:\Python27\Scripts\pip.exe" install virtualenv D:\Projects\MyProject>"C:\Python27\Scripts\virtualenv.exe" venv D:\Projects\MyProject>venv\Scripts\activate.bat D:\Projects\MyProject>pip install -r requirements.txt
排查后的一致点
where python和where pip均正确指向虚拟环境路径python -V和pip -V显示版本与系统环境完全一致(Python 2.7、pip 20.3.4)pip freeze输出的模块及版本与系统环境完全匹配
虚拟环境中的错误信息
Traceback (most recent call last): File "myScript_performWebQuery.py", line 504, in <module> searchResult = fn_RetrieveTitle(varInput[0], varInput[1]) File "myScript_performWebQuery.py", line 162, in fn_RetrieveTitle searchResult_Request = requests.get(urlQueryStr), headers={"User-agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) Trident/7.0; like Gecko"}) File "...\MyProject\venv\lib\site-packages\requests\api.py", line 76, in get return request('get', url, params=params, **kwargs) File "...\MyProject\venv\lib\site-packages\requests\api.py", line 61, in request return session.request(method=method, url=url, **kwargs) File "...\MyProject\venv\lib\site-packages\requests\sessions.py", line 542, in request resp = self.send(prep, **send_kwargs) File "...\MyProject\venv\lib\site-packages\requests\sessions.py", line 655, in send r = adapter.send(request, **kwargs) File "...\MyProject\venv\lib\site-packages\requests\adapters.py", line 514, in send raise SSLError(e, request=request) requests.exceptions.SSLError: HTTPSConnectionPool(host='https://webscraper.io/test-sites/e-commerce/allinone', port=443): Max retries exceeded with url: /test-sites/e-commerce/allinone (Caused by SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)'),))
虚拟环境模块列表(pip freeze输出)
backports.functools-lru-cache==1.6.4 beautifulsoup4==4.9.3 bs4==0.0.1 certifi==2020.12.5 cffi==1.15.1 chardet==4.0.0 cryptography==3.3.2 docopt==0.6.2 enum34==1.1.10 ez-setup==0.9 idna==2.10 ipaddress==1.0.23 lxml==4.6.3 ndg-httpsclient==0.5.1 num2words==0.5.12 numpy==1.16.6 opencv-python==4.2.0.32 pyasn1==0.4.8 pycparser==2.21 pyOpenSSL==21.0.0 pysrt==1.1.2 requests==2.25.1 six==1.16.0 soupsieve==1.9.6 urllib3==1.26.12
系统环境:Windows 10
原因分析
- 脚本存在语法错误:错误信息中显示的代码行有明显语法问题——
requests.get(urlQueryStr)后面多了一个右括号,导致headers参数传递失败,间接引发请求异常。 - 虚拟环境未继承系统根证书:系统环境的Python会自动调用Windows内置的根证书存储,而虚拟环境中依赖的certifi包自带独立证书库,可能缺少目标网站的信任根证书,或与系统信任的证书不匹配。
- Python 2.7的SSL兼容性限制:Python 2.7对现代SSL协议和证书链的支持有限,虚拟环境中certifi、pyOpenSSL等依赖的组合可能存在兼容性问题,导致证书验证逻辑异常。
解决方法
第一步:修复脚本语法错误
先修正代码中的括号错误,这是基础前提:
# 错误写法(多了一个右括号) searchResult_Request = requests.get(urlQueryStr), headers={"User-agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) Trident/7.0; like Gecko"}) # 正确写法 searchResult_Request = requests.get(urlQueryStr, headers={"User-agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) Trident/7.0; like Gecko"})
方法1:让requests使用系统证书存储
强制虚拟环境中的requests调用Windows系统根证书,替代certifi的内置证书库:
- 脚本内临时设置:
import os import requests # 指定Windows系统证书路径(可根据实际情况调整) os.environ['REQUESTS_CA_BUNDLE'] = os.path.join(os.environ['SYSTEMROOT'], 'System32', 'certsrv', 'certenroll', 'localhost.crt') # 或直接使用系统证书存储(测试场景下可临时禁用验证,注意安全风险) searchResult_Request = requests.get(urlQueryStr, headers=headers, verify=False) - 虚拟环境永久设置:
激活虚拟环境后执行以下命令:setx REQUESTS_CA_BUNDLE "C:\Windows\System32\certsrv\certenroll\<你的系统证书文件名>.crt"
方法2:更新或替换certifi证书库
虚拟环境中的certifi版本为2020.12.5,较旧可能缺少新根证书:
- 更新certifi包:
pip install --upgrade certifi - 若更新无效,复制系统环境的证书库到虚拟环境:
- 在系统Python中执行
python -c "import certifi; print(certifi.where())",获取系统certifi的证书文件路径 - 将该文件复制到虚拟环境对应路径:
...\MyProject\venv\lib\site-packages\certifi\cacert.pem,替换原文件
- 在系统Python中执行
方法3:重新安装SSL相关依赖
Python 2.7虚拟环境可能未正确关联SSL库,重新安装依赖确保兼容性:
pip uninstall pyOpenSSL cryptography -y pip install pyOpenSSL==21.0.0 cryptography==3.3.2
若安装失败,可下载对应版本的预编译whl文件(适配Python 2.7和Windows 10)手动安装。
内容的提问来源于stack exchange,提问作者Lorena
相关产品推荐
相关产品推荐

