Windows下嵌入自行编译的Python 3.13.9时,初始化阶段报错无法找到encodings模块或崩溃的解决求助
兄弟我太懂你这种踩坑的痛苦了!Windows下自编译Python做C++嵌入确实比Linux麻烦N倍,尤其是路径和初始化的坑特别多,我之前做类似的项目也卡过好久,结合你的场景给你捋捋精准的解决步骤:
先搞懂核心问题根源
你遇到的两个错误本质是同一个:Python运行时找不到它的核心依赖文件(encodings模块在Lib/encodings下,还有python313.dll等核心库)。命令行下正常是因为系统自动帮你处理了路径,但C++嵌入时需要手动给Python指对路,而且自编译版的路径逻辑和官方预编译版还不一样!
步骤1:修正PYTHONHOME和PYTHONPATH的正确打开方式
别再纠结要不要设置这俩变量了——Windows下自编译Python嵌入必须设置,但要指对地方:
- PYTHONHOME不能瞎设:它必须指向你的Python源码根目录(就是包含
Lib文件夹的那个目录,比如你的C:\Python-3.13.9),因为encodings模块默认在PYTHONHOME/Lib/encodings下。 - PYTHONPATH要包含三个关键路径:
PYTHONHOME/Lib:核心模块所在PYTHONHOME/Lib/site-packages:第三方包路径PYTHONHOME/PCbuild/amd64:编译生成的DLL和工具所在
- 设置时机很重要:必须在调用
Py_Initialize()或者Py_InitializeFromConfig()之前设置环境变量,Python初始化时只会读一次这些变量!
给你个代码里设置的示例(比系统环境变量更可靠,避免全局污染):
#define PY_SSIZE_T_CLEAN #include <Python.h> #include <cstdlib> int main() { // 先硬编码设置环境变量(调试阶段用,后续可以改成配置文件) _wputenv(L"PYTHONHOME=C:\\Python-3.13.9"); _wputenv(L"PYTHONPATH=C:\\Python-3.13.9\\Lib;C:\\Python-3.13.9\\Lib\\site-packages;C:\\Python-3.13.9\\PCbuild\\amd64"); Py_Initialize(); if (Py_IsInitialized()) { PyRun_SimpleString("from time import time,ctime\nprint('Today is', ctime(time()))\n"); Py_FinalizeEx(); } else { printf("Python初始化失败!"); } return 0; }
步骤2:解决PyConfig初始化的崩溃问题(错误码0xc0000374)
你设置了config.isolated = 1,这是大坑!isolated模式会让Python完全忽略系统环境变量,你之后从环境变量读PYTHONHOME/PYTHONPATH的代码等于白写,而且还会导致Python找不到核心库,触发堆损坏的崩溃。
如果一定要用PyConfig(推荐用,更灵活),这么改:
#define PY_SSIZE_T_CLEAN #include <Python.h> int main(int argc, char** argv) { PyStatus status; PyConfig config; PyConfig_InitPythonConfig(&config); // 关闭isolated模式,或者手动在config里指定所有路径(isolated模式下不能用环境变量) config.isolated = 0; // 手动设置Python的home目录(不要用临时字符串的c_str(),避免悬空指针) const wchar_t* python_home = L"C:\\Python-3.13.9"; status = PyConfig_SetString(&config, &config.home, python_home); if (PyStatus_Exception(status)) goto exception; // 手动设置模块搜索路径 status = PyWideStringList_Append(&config.module_search_paths, L"C:\\Python-3.13.9\\Lib"); if (PyStatus_Exception(status)) goto exception; status = PyWideStringList_Append(&config.module_search_paths, L"C:\\Python-3.13.9\\Lib\\site-packages"); if (PyStatus_Exception(status)) goto exception; status = PyWideStringList_Append(&config.module_search_paths, L"C:\\Python-3.13.9\\PCbuild\\amd64"); if (PyStatus_Exception(status)) goto exception; // 设置可执行文件路径(用PyConfig_SetString避免指针问题) const wchar_t* exe_path = L"C:\\Python-3.13.9\\PCbuild\\amd64\\python.exe"; status = PyConfig_SetString(&config, &config.executable, exe_path); if (PyStatus_Exception(status)) goto exception; // 初始化Python status = Py_InitializeFromConfig(&config); if (PyStatus_Exception(status)) goto exception; PyRun_SimpleString("from time import time,ctime\nprint('Today is', ctime(time()))\n"); PyConfig_Clear(&config); Py_FinalizeEx(); return 0; exception: PyConfig_Clear(&config); if (PyStatus_IsExit(status)) { return status.exitcode; } Py_ExitStatusException(status); }
关键提醒:永远不要用临时std::wstring的c_str()给PyConfig赋值,临时对象销毁后指针会悬空,直接触发堆损坏(就是你遇到的0xc0000374错误),一定要用PyConfig_SetString或者静态字符串。
步骤3:CMake和VS2022的配置检查
- 确保架构一致:你的C++项目必须是
x64架构,和你编译的Python(amd64)匹配,32位和64位混调用必炸。 - CMake正确链接自编译Python:别让CMake自动找系统Python,手动指定你的自编译版本的路径:
cmake_minimum_required(VERSION 3.24) project(PythonEmbedDemo) set(Python3_ROOT_DIR "C:/Python-3.13.9/PCbuild/amd64") find_package(Python3 3.13 EXACT REQUIRED COMPONENTS Development) add_executable(PythonEmbedDemo main.cpp) target_include_directories(PythonEmbedDemo PRIVATE ${Python3_INCLUDE_DIRS}) target_link_libraries(PythonEmbedDemo PRIVATE ${Python3_LIBRARIES}) # 编译后自动复制Python的DLL到输出目录(可选,但省心) add_custom_command(TARGET PythonEmbedDemo POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${Python3_ROOT_DIR}/python313.dll" $<TARGET_FILE_DIR:PythonEmbedDemo> ) - 复制Lib目录到输出目录:调试阶段可以手动把
C:\Python-3.13.9\Lib复制到你的C++程序的exe所在目录,这样就算环境变量没设置对也能跑,方便排查问题。
最后检查自编译Python的完整性
打开你自编译的python.exe(在PCbuild/amd64下),输入这两行命令:
import encodings print(encodings.__file__)
如果输出的路径是C:\Python-3.13.9\Lib\encodings\__init__.py,说明你的Python本身是好的;如果不是,说明你编译的时候漏了东西,重新编译一遍(记得用VS的开发者命令提示符打开,运行PCbuild\build.bat --release)。
按这个步骤来,应该能解决你的问题,有啥细节卡壳的随时问!




