发生 SSLError 是因为系统 OpenSSL 库版本(编译时链接到 Python 的版本)低于 1.0.1Python 安装的那天或者您当前的 Python 版本低于 2.7.9 / 3.4,因为它们都不真正支持 Python 包索引 (PyPI) 的 TLS 1.2 协议版本现在需要 https://pyfound.blogspot.com/2017/01/time-to-upgrade-your-python-tls-v12.html from pip
连接。
如果不进行完整的操作系统升级,发行版通常无法轻松升级旧的 openssl 和系统 Python,这并不总是可取的。您可以从最近的版本编译您自己的“非系统”OpenSSLsources https://www.openssl.org/source/然后尝试编译一个独立的“非系统”Python https://www.python.org/downloads/source/将其与刚刚编译的 OpenSSL 链接起来,但有时由于各种限制,这种方法也不可行。
Solution
流行的建议,例如 pip install requests[secure] 或 urllib3[secure],通常无法帮助修复pip
因为点itself https://github.com/pypa/warehouse/issues/3411 is affected https://pyfound.blogspot.com/2018/03/warehouse-all-new-pypi-is-now-in-beta.html并且无法连接到 PyPI 来安装任何东西。我们不能要求 pip 连接到 PyPI 来修复 pip 无法连接到 PyPI 的问题。 :) 要在不升级 Python 的情况下修复它,我们需要手动安装相关包,解决依赖关系:
-
PyOpenSSL
and cryptography
(its manylinux1
Wheel 提供更新的 openssl 库);
- 他们的依赖关系:
asn1crypto
, cffi
, enum34
, idna
, ipaddress
, pycparser
, six
;
- any
pip
10+ 版本,因为较旧的 pip 版本并未真正使用加密技术 - 仅使用标准库的ssl
模块(如果您的 pip 版本已经是 10 或更高版本,则不需要新的 pip 版本,任何 pip v10+ 都可以)
在古老的 Ubuntu 上使用旧的非工作 pip 和过时的系统 openssl 版本进行了测试。
第 1 步 - 下载
Download以下软件包来自 Python Packing Index (pypi.org)通过您选择的网络浏览器-- 选择最近的多linux1轮子(.whl) 对于您的操作系统/平台:
pip https://pypi.org/project/pip/#files, asn1加密 https://pypi.org/project/asn1crypto/#files, enum34 https://pypi.org/project/enum34/#files, idna https://pypi.org/project/idna/#files, six https://pypi.org/project/six/#files, IP地址 https://pypi.org/project/ipaddress/#files, pyOpenSSL https://pypi.org/project/pyOpenSSL/#files, cffi https://pypi.org/project/cffi/#files, 密码学 https://pypi.org/project/cryptography/#files轮子;并且pyc解析器 https://pypi.org/project/pycparser/#files(非wheel,它将是tar.gz)
cp27-代表Python 2.7,cp36-对于Python 3.6;
mu-类型 Manylinux Wheel 是一个常见的选择,因为它们适用于以 UCS-4 (UTF-32) 格式存储 Unicode 数据的 Python——检查方法如下:
$ python -c "import sys; print('UCS4/UTF-32: mu-manylinux1' if sys.maxunicode > 65535 else 'UCS2/UTF-16: m-manylinux1')"
Python 3 的注意事项: the cp34-abi3-manylinux1
密码学的轮子可以与anyPython版本>=3.4,因为abi3support https://cryptography.io/en/latest/faq/#why-are-there-no-wheels-for-python-3-5-on-linux-or-macosPython3 的多个版本,例如加密-2.5-cp34-abi3-manylinux1_x86_64.whl (2.4 MB)
基本上,wheels是具有特殊格式文件名和 .whl 扩展名的 ZIP 存档,包含可重定位的 Python 包。包可以是纯python的,也可以有预编译用于 python 绑定的 C 库,因此可以安装它,而无需具有某些系统依赖项,例如 gcc、python-dev 和其他 C 头文件/库,而经典 .tar.gz 格式包通常需要这些依赖项。这还允许使用每个轮子中捆绑的程序的精确版本。这多linux1_{x86_64,i686}轮平台标签被采用PEP-513 https://www.python.org/dev/peps/pep-0513/并将致力于manyLinux 系统,包括常用的流行桌面和服务器发行版。预计多Linux2未来的标签!
只需创建一个新目录,例如:
$ mkdir ~/wheels_dir
并将所有下载的包复制(或移动)到该目录。
那里没有其他文件(除了下载的轮子),也没有子目录!
第 2 步 - 安装
如果您当前的pip
版本低于 8.1,必须先安装较新的 pip 版本,然后才能继续安装所有其他软件包:
$ pip install --user --no-index ~/wheels_dir/pip-19.0.1-py2.py3-none-any.whl
它将升级 pip 以处理新的多linux1车轮格式并有助于避免“此平台上不支持轮子” error.
要在用户主目录级别安装所有软件包:
$ pip install --user --no-index ~/wheels_dir/*
$ pip3
在Python 3中
如果安装在新的或现有的 virtualenv 中,请省略--user
option:
$ source bin/activate
$ pip install --no-index ~/wheels_dir/*
Pip 将解析正确的安装顺序和依赖项自动g确切地说。
(如果需要的话,也可以为此创建一个requirements.txt)
Note:除非您安装在 Python virtualenv 或 venv 中,否则强烈建议始终使用--user
带点的标志。然后它会在 ~/.local/lib/ 你的 home 目录下部署 python 包。事实上,这个选项总是On默认情况下,在发行版修补的 pip 版本中提供python3-pip
and python-pip
包在recent流行发行版的版本,例如 Ubuntu、Debian、Fedora 等。请尝试avoid https://askubuntu.com/a/116645 sudo pip
,因为使用具有 root 访问权限的 pip 会干扰您的操作系统包管理器子系统(apt、yum 等),并且可能依赖于发行版提供的系统 python 的基本操作系统组件。
Run $ pip freeze
(or pip3 freeze
在 Python 3) 命令中检查结果并确保已为您的 Python 环境安装所有软件包。
恭喜!现在你的 pip 应该可以与 PyPI 一起使用,你可以尝试查找类似的内容pip search colorama
来自在线 PyPI 存储库。
Verify
您可以通过查询已安装的 SSL/TLS 设置来查看系统 SSL/TLS 设置的详细摘要pyOpenSSL
直接lib:
$ python -m OpenSSL.debug
(a 模块未找到错误意味着 pyOpenSSL 软件包未安装)
密码学的链接 OpenSSL 共享库不会与您的系统 Python 的 openssl 版本发生任何冲突。现在可能是一个很好的机会,可以通过安装最新的 python 来更新您的根 SSL 证书集合以供将来使用certifi
包裹。
为什么它有效
早期版本的 pip(10 之前)仅使用标准库的ssl
模块(这是系统 OpenSSL 库的 Python API),没有任何可能回退到其他库,例如cryptography
。从版本 10 开始,pip 现在可以将 pyOpenSSL 与加密结合使用(如果环境中存在)。
The manylinux1
的轮子cryptography
包裹includes最新的 OpenSSL 库支持高达 v1.3 的所有 TLS 协议,无论您的平台是什么(PyPI 期望 pip 支持 TLSv1.2)。这就是为什么这个轮子重 2.1 Mb —— 存档提供了一个共享库绑定:
$ strings site-packages/cryptography/hazmat/bindings/_openssl.so | grep OpenSSL -m1
OpenSSL 1.1.1a 20 Nov 2018
$ python -c "from cryptography.hazmat.backends.openssl import backend as b; print b.openssl_version_text()"
OpenSSL 1.1.1a 20 Nov 2018
$ python -c "from OpenSSL import SSL; print SSL.SSLeay_version(0)"
OpenSSL 1.1.1a 20 Nov 2018
$ python -c "import requests; print requests.get('https://www.howsmyssl.com/a/check').json()['tls_version']"
TLS 1.3
加密轮包含静态链接的 OpenSSL 绑定,可确保您可以访问最新的 OpenSSL 版本,而不会破坏系统依赖项。
这将允许您继续使用相对较旧的 Linux 发行版(例如 LTS 版本),同时确保您的 Python 程序拥有可用的最新 OpenSSL。 (https://cryptography.io/en/latest/installation/ https://cryptography.io/en/latest/installation/)
在 Python 2 中,标准库的ssl
模块从版本 2.7.9 开始显式支持 PROTOCOL_TLSv1_2 标志,而在 Python 3 中 - 从版本 3.4 开始;但 TLSv1.2 连接只能工作当且仅当支持 TLSv1.2 的系统范围 OpenSSL 库是已经可用当 Python 被编译和链接时,它就已经存在于系统中了。 TLSv1.2 至少需要 OpenSSL 1.0.1 才能运行,但通常建议使用 OpenSSL 1.0.2(或更高版本)(默认情况下使用 TLSv1.2)。
如果您有 Python 2.7.9+ 或 3.4+,及其ssl
事实上,模块是针对系统 openssl 编译的,比如 v1.0.2k,那么即使是旧的 pip(例如 v6.0.8)也会still截至撰写本文时,您正在使用 PyPI,您甚至不需要加密技术。检查Python标准库ssl
和系统 openssl 版本:
$ python -c "import ssl; print(ssl.OPENSSL_VERSION)" && openssl version
OpenSSL 0.9.8o 2010 年 6 月 1 日
即使我们升级了一些过时的发行版提供的 openssl,或者编译了最新的 openssl,我们也不能只是将现有的 Python 安装重新链接到它:ssl
模块在 Python 编译/安装时硬链接到系统提供的 OpenSSL,反之亦然。因此,基本上,如果不重新编译/重新安装 Python 本身(至少应该是 2.7.9+ / 3.4+ 版本)将其链接到新系统 openssl 库,就无法利用新的 TLS 协议。这就是上面的地方pyopenssl
+cryptography
方法可以解决问题。
TLS 快乐! :)