Cmake 在 Windows 10 上找不到 python37.dll,但文件路径在缓存文件中。 (pybind11)

Cmake can't find python37.dll on Windows 10, but file path is in the Cache file. (pybind11)

我正在 Windows 10 机器 64 位安装,在典型的“Program Files”目录中安装了 python 3.7.9(不在 Anaconda 下),并且在我的工作中安装了 pybind11目录。这里的目标只是从 C++ 中获取 pybind11 运行ning。程序编译正常,但可执行文件没有 运行,给出错误“代码执行无法继续,因为未找到 python37.dll。”重新安装程序可能会解决此问题。”但是,python37.dll(和调试版本)文件位置在生成的 CMakeCache.txt 文件中(包括在下面以及其他详细信息中)。我尝试在引号周围加上引号CMakeCache.txt 中的文件路径希望错误仅仅是由于“Program Files”目录名称中的 space,并且在环境路径变量中具有“Program Files”的短代码版本(PROGRA ~1), 但错误仍然存​​在。我是 Cmake 和 C++ 的新手。我错过了什么?

我发现的其他相关帖子涉及移动文件(https://www.reddit.com/r/techsupport/comments/c2z5rl/python37dll_not_found_but_i_find_it_in_windows/, which is not the issue here), or a system where python was not installed (, again not the case here), problems with the Anaconda installation (Why do I get a python37.dll error when starting jupyter notebook via conda,但我没有 运行ning Anaconda)或我未使用的其他软件。所有其他链接都指向下载站点。


两个程序的安装过程都没有错误。程序目录、相关代码、构建命令和输出结果如下。

在 ./NewKamodo/build 目录中,在 cmd 提示符下执行命令,输出为(出于隐私考虑,我已将我的内部结构替换为 ...):

...\NewKamodo\build>cmake .. -G"Visual Studio 15 2017" -A x64  
-- Selecting Windows SDK version 10.0.17763.0 to target Windows 10.0.19041.  
-- The C compiler identification is MSVC 19.16.27045.0  
-- The CXX compiler identification is MSVC 19.16.27045.0  
-- Detecting C compiler ABI info  
-- Detecting C compiler ABI info - done  
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.exe - skipped  
-- Detecting C compile features  
-- Detecting C compile features - done  
-- Detecting CXX compiler ABI info  
-- Detecting CXX compiler ABI info - done  
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.exe - skipped  
-- Detecting CXX compile features  
-- Detecting CXX compile features - done  
-- pybind11 v2.6.3 dev1  
-- Found PythonInterp: C:/Program Files/Python37/python.exe (found version "3.7.9")  
-- Found PythonLibs: C:/Program Files/Python37/libs/python37.lib  
-- Performing Test HAS_MSVC_GL_LTCG  
-- Performing Test HAS_MSVC_GL_LTCG - Success  
-- Found Python3: C:/Program Files/Python37/python.exe (found version "3.7.9") found components: Interpreter Development Development.Module Development.Embed  
-- Configuring done  
-- Generating done  
-- Build files have been written to: .../NewKamodo/build  

...\NewKamodo\build>cmake --build .  
Microsoft (R) Build Engine version 15.9.21+g9802d43bc3 for .NET Framework  
Copyright (C) Microsoft Corporation. All rights reserved.  

  Checking Build System  
  Building Custom Rule .../NewKamodo/CMakeLists.txt  
  KamodoCXX.cpp  
  KamodoCXX.vcxproj -> ...\NewKamodo\build\Debug\KamodoCXX.exe  
  Building Custom Rule .../NewKamodo/CMakeLists.txt  

...\NewKamodo\build>cd Debug  
...\NewKamodo\build\Debug>KamodoCXX.exe  

弹出 window 错误:“代码执行无法继续,因为未找到 python37.dll。重新安装程序可能会解决此问题。”


我的程序目录结构是:
新卡莫多


KamodoCXX.cpp 中的 C++ 代码是取自 https://pybind11.readthedocs.io/en/stable/advanced/embedding.html 并在下面复制的 hello world 示例。

#include <pybind11/embed.h> // everything needed for embedding
namespace py = pybind11;

int main() {
    py::scoped_interpreter guard{}; // start the interpreter and keep it alive

    py::print("Hello, World!"); // use the Python API
}

CMakeLists.txt文件也很简单:

cmake_minimum_required(VERSION 3.4)
project(KamodoCXX)

#specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_REQUIRED True)

add_subdirectory(pybind11)
find_package(Python3 COMPONENTS Interpreter Development)

add_executable(KamodoCXX KamodoCXX.cpp)
target_link_libraries(KamodoCXX PRIVATE pybind11::embed)

CMakeCache.txt 内容(python 部分文件只是为了简洁):
...

PYBIND11_INCLUDE_DIR:INTERNAL=.../NewKamodo/pybind11/include
//ADVANCED property for variable: PYTHON_EXECUTABLE
PYTHON_EXECUTABLE-ADVANCED:INTERNAL=1
PYTHON_INCLUDE_DIRS:INTERNAL=C:/Program Files/Python37/include
PYTHON_IS_DEBUG:INTERNAL=0
PYTHON_LIBRARIES:INTERNAL=C:/Program Files/Python37/libs/python37.lib
PYTHON_MODULE_EXTENSION:INTERNAL=.cp37-win_amd64.pyd
PYTHON_MODULE_PREFIX:INTERNAL=
PYTHON_VERSION:INTERNAL=3.7.9
PYTHON_VERSION_MAJOR:INTERNAL=3  
PYTHON_VERSION_MINOR:INTERNAL=7  
Python_ADDITIONAL_VERSIONS:INTERNAL=3.10;3.9;3.8;3.7;3.6;3.5;3.4  
//CMAKE_INSTALL_PREFIX during last run  
_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX:INTERNAL=C:/Program Files/KamodoCXX  
_Python:INTERNAL=PYTHON  
_Python3_DEVELOPMENT_EMBED_SIGNATURE:INTERNAL=78025eb1b345e021c9dadb673f40d7b6  
_Python3_DEVELOPMENT_MODULE_SIGNATURE:INTERNAL=78025eb1b345e021c9dadb673f40d7b6  
//Path to a program.  
_Python3_EXECUTABLE:INTERNAL=C:/Program Files/Python37/python.exe  
//Path to a file.  
_Python3_INCLUDE_DIR:INTERNAL=C:/Program Files/Python37/include  
//Python3 Properties  
_Python3_INTERPRETER_PROPERTIES:INTERNAL=Python;3;7;9;64;;cp37-win_amd64;C:\Program Files\Python37\Lib;C:\Program Files\Python37\Lib;C:\Program Files\Python37\Lib\site-packages;C:\Program Files\Python37  \Lib\site-packages  
_Python3_INTERPRETER_SIGNATURE:INTERNAL=d8451d76c667fb34c5414ba253c4dadd  
//Path to a library.  
_Python3_LIBRARY_DEBUG:INTERNAL=C:/Program Files/Python37/libs/python37_d.lib  
//Path to a library.  
_Python3_LIBRARY_RELEASE:INTERNAL=C:/Program Files/Python37/libs/python37.lib  
//Path to a library.  
_Python3_RUNTIME_LIBRARY_DEBUG:INTERNAL=C:/Program Files/Python37/python37_d.dll  
//Path to a library.  
_Python3_RUNTIME_LIBRARY_RELEASE:INTERNAL=C:/Program Files/Python37/python37.dll  
//True if pybind11 and all required components found on the system
pybind11_FOUND:INTERNAL=TRUE  
//Directory where pybind11 headers are located  
pybind11_INCLUDE_DIR:INTERNAL=.../NewKamodo/pybind11/include  
//Directories where pybind11 and possibly Python headers are located  
pybind11_INCLUDE_DIRS:INTERNAL=.../NewKamodo/pybind11/include;C:/Program Files/Python37/include 

这是我们过去对 python 2.7 所做的,但它可能适用于 3+。我们通过 运行 python 从 cmake 获得 python 库的完整路径。

add_subdirectory(pybind11)
find_package(Python3 COMPONENTS Interpreter Development)
FIND_PACKAGE(PythonLibs "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}" REQUIRED)
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import sys; from distutils.sysconfig import get_python_lib; print(get_python_lib().split(sys.prefix)[-1][1:])"
                    OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)

*为 python3

编辑

我与 Pybind11 开发人员一起解决这个 BUG post 以实现最终解决方案,我在下面总结。沿途弹出的替代错误是:

Fatal Python Error: initfsencoding: unable to load the file system codec
ModuleNotFoundError: No module named ‘encodings’

尝试从命令提示符 运行 可执行文件时。

https://github.com/pybind/pybind11/issues/2855#issuecomment-777648383


在 Windows 10(不使用 linux 的 windows 子系统):

  • 安装 Anaconda 或 miniconda
  • 使用命令构建conda环境
conda create -n embedtest -c conda-forge python==3.7.9 pybind11==2.6.2 cmake=3.19.4
conda activate embedtest

注意:任何高于 3.15 的 cmake 版本似乎都可以使用。我没有指定 pybind11 或 cmake 的哪个版本,并成功使用了 cmake 3.19.4。 (Pybind11 版本 2.6.2 是当前默认值)。此外,避免使用 3.8 或 3.9 的 python 版本,因为这些版本已知无法正常工作(请参阅 pybind11 文档)。

CMakeLists.txt内容:

cmake_minimum_required(VERSION 3.15)
project(main)

find_package(Python COMPONENTS Interpreter Development) 
find_package(pybind11 REQUIRED)

add_executable(main main.cpp)
target_link_libraries(main pybind11::embed)
  • 下一步 运行 来自 windows 命令提示符的以下命令,其中激活了 conda 环境并且您已移动到与 main.cpp 和 CMakeLists.txt 相同的目录文件位于。请注意,-B 命令在名为 build.
  • 的子目录中构建输出
cmake -B build -A x64
cmake --build build
set PYTHONHOME=C:\Users\test\Miniconda3\venvs\embedtest
build\Debug\main.exe

注意:必须从终端设置 PYTHONHOME 变量,因为使用 cmake 设置此变量不会使新定义在构建时或执行时可用,从而导致错误。这里给出的目录示例是python可执行文件在conda环境下的位置,在找到python包后在CMakeLists.txt代码中加入下面一行即可轻松获取使用 find_package(Python 组件 ....)

message(STATUS ${Python_EXECUTABLE})

如果您的目标是在没有虚拟环境的情况下使用 pybind11,则 set(Python_VIRTUALENV ONLY) 行将不是必需的,但调用的 python 版本将是默认安装的版本。


如果您希望通过 WSL 在 Windows10 上使用 pybind11,则说明几乎相同。 CMakeLists.txt和main.cpp文件是一样的,只是终端命令略有不同:

cmake -B build
cmake --build build
cd build
chmod +x main
./main

我在使用 MSVC 编译器和可通过 python.org 下载的 python 3.10 版本时遇到此错误,并且同样感到困惑,因为我使用的是 64 位 MSVC 编译器和 64 位python 3.10 库。如果它是 pybind11 中的错误,它仍然没有被修复(我今天使用的是 master 分支)。但是,通过使用 mingw 编译器,我无需切换到 conda 即可解决该错误,即:

cmake -S . -B builddir -G "MinGW Makefiles"
cmake --build builddir