You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Windows下嵌入自行编译的Python 3.13.9时,初始化阶段报错无法找到encodings模块或崩溃的解决求助

Windows下嵌入自行编译的Python 3.13.9时,初始化阶段报错无法找到encodings模块或崩溃的解决求助

兄弟我太懂你这种踩坑的痛苦了!Windows下自编译Python做C++嵌入确实比Linux麻烦N倍,尤其是路径和初始化的坑特别多,我之前做类似的项目也卡过好久,结合你的场景给你捋捋精准的解决步骤:

先搞懂核心问题根源

你遇到的两个错误本质是同一个:Python运行时找不到它的核心依赖文件(encodings模块在Lib/encodings下,还有python313.dll等核心库)。命令行下正常是因为系统自动帮你处理了路径,但C++嵌入时需要手动给Python指对路,而且自编译版的路径逻辑和官方预编译版还不一样!


步骤1:修正PYTHONHOME和PYTHONPATH的正确打开方式

别再纠结要不要设置这俩变量了——Windows下自编译Python嵌入必须设置,但要指对地方:

  1. PYTHONHOME不能瞎设:它必须指向你的Python源码根目录(就是包含Lib文件夹的那个目录,比如你的C:\Python-3.13.9),因为encodings模块默认在PYTHONHOME/Lib/encodings下。
  2. PYTHONPATH要包含三个关键路径
    • PYTHONHOME/Lib:核心模块所在
    • PYTHONHOME/Lib/site-packages:第三方包路径
    • PYTHONHOME/PCbuild/amd64:编译生成的DLL和工具所在
  3. 设置时机很重要:必须在调用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的配置检查

  1. 确保架构一致:你的C++项目必须是x64架构,和你编译的Python(amd64)匹配,32位和64位混调用必炸。
  2. 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>
    )
    
  3. 复制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)。

按这个步骤来,应该能解决你的问题,有啥细节卡壳的随时问!

火山引擎 最新活动