问题描述
我正在 Windows 10 机器上进行 64 位安装,python 3.7.9 安装在典型的“Program Files”目录中(不在 Anaconda 下),pybind11 安装在我的工作目录中。这里的目标只是让 pybind11 从 C++ 运行。程序编译正常,但可执行文件不运行,给出错误“代码执行无法继续,因为找不到 python37.dll。”重新安装程序可能会解决这个问题。”但是,python37.dll(和调试版本)文件位置在生成的 CMakeCache.txt 文件中(包括在下面以及其他详细信息)。我尝试在 CMakeCache 中的文件路径周围加上引号.txt 希望错误只是由于“Program Files”目录名中的空格,并且在环境路径变量(PROGRA~1)中有“Program Files”的短代码版本,但错误仍然存在。我我是 Cmake 和 C++ 的新手。我缺少什么?
我发现的其他相关帖子涉及移动文件(https://www.reddit.com/r/techsupport/comments/c2z5rl/python37dll_not_found_but_i_find_it_in_windows/,这不是这里的问题),或未安装 python 的系统(python37.dll not linked in executable,这里也不是这种情况),问题使用 Anaconda 安装(Why do I get a python37.dll error when starting jupyter notebook via conda,但我没有运行 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
弹出窗口错误:“代码执行无法继续,因为没有找到python37.dll。重新安装程序可能会解决这个问题。”
我的程序目录结构是:
新卡莫多
- ./build
- ./pybind11
- CMakeLists.txt
- KamodoCXX.cpp
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+
。我们通过从 cmake 运行 python 来获取 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 帖子上合作以实现最终解决方案,我将在下面进行总结。沿途弹出的替代错误是:
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 文档)。
- 接下来,将以下文本复制到与 pybind11 网站 (https://pybind11.readthedocs.io/en/stable/advanced/embedding.html) 上的 main.cpp 文件相同目录中的 CMakeLists.txt 文件中。
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环境中的位置,在使用find_package(Python COMPONENTS ....)找到python包后,通过在CMakeLists.txt代码中添加以下行即可轻松获取
message(STATUS ${Python_EXECUTABLE})
如果您的目标是在没有虚拟环境的情况下使用 pybind11,则不需要 set(Python_VIRTUALENV ONLY) 行,但调用的 Python 版本将是默认安装的版本。
如果您希望通过 WSL 在 Windows 10 上使用 pybind11,那么说明几乎相同。 CMakeLists.txt 和 main.cpp 文件相同,但终端命令略有不同:
cmake -B build
cmake --build build
cd build
chmod +x main
./main