pip cryptography 报错 1120? 轻松修复 link.exe 失败
2025-04-02 04:22:31
搞定 pip install cryptography 报错:link.exe
failed with exit status 1120
装 Python 包 cryptography
的时候,你可能兴冲冲地敲下 pip install cryptography
,结果屏幕喷出一大堆红字,最后一句是扎眼的 error: command '...link.exe' failed with exit status 1120
。别灰心,这问题虽然看起来吓人,但通常不是啥绝症。咱们来捋一捋,看看怎么干掉它。
遇到这个报错,说明 pip 在尝试编译 cryptography
包里的 C 语言扩展模块时,在最后“链接”那一步栽了跟头。link.exe
是 Visual Studio C++ 编译器工具链里负责把编译好的目标文件(.obj
)和库文件(.lib
)“粘”在一起,生成最终的可执行文件(.pyd
,也就是 Python 能加载的 DLL)的工具。错误码 1120
赤裸裸地告诉你:“有几个零件找不到了!” 具体是哪些零件呢?错误日志里通常会跟 LNK2001 或 LNK2019 错误,列出找不到的“外部符号”(unresolved external symbol),比如 sscanf
, _vsnwprintf
, __iob_func
, fprintf
这类看着眼熟的 C 标准库函数。
哪儿出问题了?刨根问底
为啥链接器 link.exe
会找不到这些基本函数?主要原因就那么几个:
- 编译环境残缺或不匹配:
cryptography
这种带 C 扩展的 Python 包,在 Windows 上编译需要 Visual Studio C++ 构建工具。如果你没装,或者装的版本不对(比如你的 Python 是用 VS 2015 编译的,你却只装了 VS 2019 的构建工具),或者安装时没选对必要的组件(比如 C++ 桌面开发工作负载、Windows SDK),那编译链接时就可能缺胳膊少腿。Python 3.5 通常需要 Visual Studio 2015 (VC++ 14.0)。 - 依赖库(OpenSSL)配置不当或版本冲突:
cryptography
依赖 OpenSSL。你在错误日志里设置了INCLUDE
和LIB
环境变量,指向了C:\ProgramData\Runtime\OpenSSL
。这很好,但问题是,你这个 OpenSSL 版本是咋来的?它是用跟你当前尝试编译cryptography
的 Visual Studio 版本兼容的设置编译的吗?特别是,它链接的 C 运行时库(CRT)是啥版本?是多线程静态 (/MT
) 还是多线程动态 (/MD
)?Debug 版还是 Release 版?如果 Python、cryptography
的 C 扩展、你提供的 OpenSSL 库,它们仨在 CRT 配置上“三观不合”,链接时就互相不认,导致找不到符号。错误日志里提到了libeay32mt.lib
和ssleay32mt.lib
,这个mt
后缀通常暗示是多线程静态库,你需要确认这是否与你的 Python 3.5(通常是动态链接 /MD)兼容。 - 环境变量抽风: 虽然你设置了
INCLUDE
和LIB
,但有可能PATH
里有其他冲突的库文件或工具链,或者vsvars*.bat
(设置 VS 编译环境的脚本)没正确运行,导致编译器或链接器用的还是错误的路径或配置。你提供的PATH
相当长,检查里面是否有多个版本的 VS 工具或 OpenSSL 库路径可能会互相干扰。 - Python 版本和目标架构不匹配: 你用的是 64 位的 Windows 和 Python 3.5.0a4 (看起来是 amd64)。编译时要确保使用的是 64 位的 VS 构建工具 (
amd64
target),并且链接的库也是 64 位的。你运行vsvars32.bat
,这通常是设置 32 位环境的,可能需要用vcvarsall.bat amd64
来设置 64 位编译环境。 - Visual Studio 2015 和 UCRT 的小坑: VS 2015 开始使用 Universal CRT (UCRT)。有些旧代码或库(比如你手动提供的 OpenSSL)在链接到 UCRT 时,可能需要特定的 Windows SDK 版本或者链接
legacy_stdio_definitions.lib
这类库来解决__iob_func
,sscanf
等函数的缺失问题。
对症下药:解决方案走起
别慌,咱们一步步来试试看能不能搞定。
方案一:拥抱 Wheel,告别编译(推荐)
最省事儿的办法,就是别在本地编译了,直接用别人预编译好的二进制包 (Wheel, .whl
文件)。
- 原理: PyPI 上通常会提供针对主流操作系统和 Python 版本的预编译 Wheel 包。pip 优先下载和安装 Wheel 包,这样就跳过了本地编译 C 扩展的步骤,自然也就没有链接错误了。
- 操作步骤:
- 升级 pip、setuptools 和 wheel 到最新版,它们对 Wheel 支持更好:
python -m pip install --upgrade pip setuptools wheel
- 然后,直接尝试安装
cryptography
:
pip 会自动查找适合你环境(Windows x64, Python 3.5)的 Wheel 包。如果找到了,安装会很快完成,直接跳过编译环节。pip install cryptography
- 升级 pip、setuptools 和 wheel 到最新版,它们对 Wheel 支持更好:
- 注意:
- 对于比较老旧或者非稳定版(比如你的 Python 3.5.0a4)的 Python,可能找不到对应的 Wheel 包,pip 还是会尝试源码编译。
- 网络环境不好的话,下载 Wheel 包可能失败。
方案二:配齐配对编译环境
如果找不到 Wheel,或者你非要从源码编译不可,那就得确保编译环境是“原配”的。
-
原理: 保证 Python、Visual Studio C++ 构建工具、OpenSSL 库三者的版本和配置(尤其是 CRT 链接方式)相互兼容。
-
操作步骤:
-
确认并安装正确的 Visual Studio 构建工具:
- Python 3.5 需要 Visual Studio 2015 (VC++ 14.0)。如果你没装,去微软官网下载 Visual Studio 2015 (Community 版免费) 或 Visual Studio Build Tools 2015。
- 安装时,务必勾选 "Programming Languages" -> "Visual C++" 下的 "Common Tools for Visual C++ 2015" 和 "Microsoft Foundation Classes (MFC)"。
- 同时,确保安装了合适的 Windows SDK。VS 2015 安装程序通常会带一个默认的 Windows 10 SDK,包含了 UCRT,这对于链接是必须的。检查“Universal Windows App Development Tools” -> “Windows 10 SDK” 是否安装。
-
处理 OpenSSL 依赖(关键):
- 方法一 (推荐): 移除手动配置,让
cryptography
自己搞定。 很多现代 Python 包(包括较新版的cryptography
)在编译时能够自动处理 OpenSSL 依赖,或者依赖于像pyOpenSSL
这样也可能提供预编译库的包。先把你手动设置的INCLUDE
和LIB
环境变量 删掉 试试。
然后尝试# 在你的命令行里临时移除环境变量(或者永久修改系统环境变量后重启命令行) set INCLUDE= set LIB=
pip install cryptography
。 - 方法二: 获取兼容的 OpenSSL 预编译库。 如果非要手动指定 OpenSSL,你需要找到一个明确是用 Visual Studio 2015 (VC14) 为 64位 (x64) 编译的,并且 动态链接 CRT (/MD) 的 OpenSSL 版本。可以去一些提供 Windows 版 OpenSSL 预编译库的网站找(比如 Shining Light Productions ,注意选择正确的 VC 版本和架构)。下载后,解压,然后 确保 你设置的
INCLUDE
指向include
目录,LIB
指向包含.lib
文件的lib
目录(不要 指向lib\VC\static
那个静态库目录,除非你百分百确定需要静态链接且知道如何处理 CRT 冲突)。
- 方法一 (推荐): 移除手动配置,让
-
清理环境,使用正确的 VS 环境启动脚本:
- 删掉之前的编译残留。可以运行
pip cache purge
清理 pip 缓存。手动删除S:\Temp\Local\
下的pip-build-*
目录。 - 最好在 Python 虚拟环境里操作,避免污染全局环境。
# 创建虚拟环境 (如果还没创建) python -m venv myenv # 激活虚拟环境 myenv\Scripts\activate
- 启动正确的 VS 编译环境。 不要用
vsvars32.bat
。打开 "VS 2015 x64 Native Tools Command Prompt" (或者在普通 CMD 里运行vcvarsall.bat amd64
) 来配置 64 位编译环境。
运行后,检查# 在已经安装了 VS 2015 的机器上,这个命令应该能配置好环境 "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
INCLUDE
,LIB
,PATH
环境变量是否包含了 VS 14.0 和 Windows SDK 的 x64 路径。
- 删掉之前的编译残留。可以运行
-
重新尝试编译安装:
- 在正确配置好的 VS 编译环境 的命令行里(虚拟环境也已激活),并且已经处理好 OpenSSL (要么移除手动设置,要么设置了正确的兼容库路径),再次尝试安装。可以加上
--no-binary :cryptography:
强制编译,以便测试你的编译环境是否真的配好了。pip install cryptography --no-binary :cryptography:
- 在正确配置好的 VS 编译环境 的命令行里(虚拟环境也已激活),并且已经处理好 OpenSSL (要么移除手动设置,要么设置了正确的兼容库路径),再次尝试安装。可以加上
-
-
安全建议: 从非官方渠道下载 OpenSSL 预编译库时,要确认来源的可信度。
方案三:升级 Python 版本
和过时的、还是 Alpha 版的 Python 3.5.0a4 死磕可能得不偿失。
- 原理: 新版本的 Python (例如 Python 3.7+) 通常对 Windows 编译环境的支持更好,其依赖的 Visual Studio 版本也更现代 (比如 Python 3.7-3.9 依赖 VS 2017,3.10+ 依赖 VS 2019 或更高),相关的生态(包括
cryptography
的 Wheel 包)也更完善。 - 操作步骤:
- 去 Python 官网 下载一个最新的稳定版 Python (比如 3.9, 3.10, 3.11 等,检查
cryptography
对 Python 版本的支持)。 - 安装新 Python,记得勾选 "Add Python to PATH"。
- 为新 Python 创建一个新的虚拟环境。
- 在新环境里,升级 pip 工具后直接尝试
pip install cryptography
。大概率能直接找到 Wheel 包并成功安装。
- 去 Python 官网 下载一个最新的稳定版 Python (比如 3.9, 3.10, 3.11 等,检查
方案四:换个环境试试?(WSL 或 Docker)
如果 Windows 环境下 C 扩展编译总是让你头疼,可以考虑在更“友好”的环境中开发。
- 原理: Linux 环境下通常 C 编译器和库的管理更直接方便。WSL (Windows Subsystem for Linux) 或 Docker 容器能提供一个 Linux 环境。
- WSL:
- 启用 WSL 功能,安装一个 Linux 发行版 (如 Ubuntu)。
- 在 WSL 的 Linux 环境里安装 Python 和 pip,然后
pip install cryptography
通常会顺利很多,因为它可能使用系统自带的 OpenSSL 开发库,或者编译过程更顺畅。
- Docker:
- 编写一个 Dockerfile,基于官方 Python 镜像,在里面用
RUN pip install cryptography
来安装。这样可以构建一个包含所有依赖的隔离环境。
- 编写一个 Dockerfile,基于官方 Python 镜像,在里面用
- 适宜性: 这两种方式需要额外学习成本,改变了开发流程,看是否适合你的项目和习惯。
通常来说,优先尝试 方案一 (使用 Wheel) ,简单高效。如果不行,仔细检查并配置好 方案二 (编译环境) 是解决 link.exe
报错的根本途径,尤其是 OpenSSL 库的兼容性问题。方案三 (升级 Python) 是一个非常务实的建议,可以避免很多历史遗留问题。方案四则是改变环境的大招。
希望这些方法能帮你摆脱 link.exe failed with exit status 1120
的困扰!