使用 pybind11 嵌入 python.虚拟环境不起作用 [英] Embedding python with pybind11. Virtual environment doesn't work

查看:51
本文介绍了使用 pybind11 嵌入 python.虚拟环境不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个简单的 c++ 应用程序,它使用 googletrans python 库翻译短语.为此,我选择了 pybind11嵌入 python.我也使用 cmake 进行代码配置.

当我使用全局 python 安装时一切正常,但是 我不明白如何使用 pybind 的虚拟环境 以及设置正确的 python 解释器、路径等的整个过程. 在 cmake 中.

我发现了这个 stackoverflow 线程:将 pybind11 嵌入虚拟环境

我像@ipa 一样设置了所有变量.看看CMakeLists.txtmain.cpp:

cmake_minimum_required(VERSION 3.15)项目(cpp_google_trans")放(PYTHON_EXECUTABLE "${CMAKE_HOME_DIRECTORY}/venv/Scripts/python.exe"CACHE FILEPATH "python 虚拟环境可执行文件")消息(状态PYTHON_EXECUTABLE 现在是:${PYTHON_EXECUTABLE}")#DEBUG设置(ENV{PYTHONPATH}${CMAKE_HOME_DIRECTORY}/venv/Lib/site-packages")消息(状态ENV{PYTHONPATH} 现在是:$ENV{PYTHONPATH}")#DEBUG放(环境{路径}"${CMAKE_HOME_DIRECTORY}/venv/Scripts/;${CMAKE_HOME_DIRECTORY}/venv/Lib")消息(状态路径现在是:$ENV{PATH}")#DEBUG添加子目录(pybind11)add_executable(app main.cpp)target_link_libraries(应用程序私有 pybind11::embed)

main.cpp:

#include #include <字符串>#include 命名空间 py = pybind11;int main() {py::scoped_interpreter 守卫{};auto sys = py::module::import("sys");py::print("Hello, World from Python!");py::print(sys.attr("可执行文件"));py::print(sys.attr("version"));system("设置路径");std::cin.get();//系统(powershell");//我在 powershell 中查看环境变量,但是我在 CMakeLists.txt 中没有设置任何变量//在这里我尝试导入 googletrans 包时得到 abort().//包安装在venv虚拟环境中.//当包被全局安装时,没有任何问题.py::object Translator = py::module::import("googletrans").attr("Translator");py::object 翻译器 = Translator();std::cout <<"C++ 程序在这里!\n说出你想翻译成英文的短语:";std::string 短语;std::getline(std::cin, 短语);std::cout <<"\n\n这句话的英文意思是:";std::cout <<translate.attr("translate")(py::cast(&phrase)).attr("text").cast();}

当查看 cmake 配置输出时,一切似乎都运行良好(而不是 PythonLibs 变量,我不知道如何更改):

-- 为:Visual Studio 16 2019 构建-- C 编译器标识为 MSVC 19.22.27812.2-- CXX 编译器标识为 MSVC 19.22.27812.2-- 检查工作的 C 编译器:C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/VC/Tools/MSVC/14.22.27812/bin/Hostx64/x64/cl.exe-- 检查 C 编译器是否工作:C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/VC/Tools/MSVC/14.22.27812/bin/Hostx64/x64/cl.exe -- 有效-- 检测 C 编译器 ABI 信息-- 检测 C 编译器 ABI 信息 - 完成-- 检测 C 编译特性-- 检测 C 编译特性 - 完成-- 检查 CXX 编译器是否工作:C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/VC/Tools/MSVC/14.22.27812/bin/Hostx64/x64/cl.exe-- 检查 CXX 编译器是否工作:C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/VC/Tools/MSVC/14.22.27812/bin/Hostx64/x64/cl.exe -- 有效-- 检测 CXX 编译器 ABI 信息-- 检测 CXX 编译器 ABI 信息 - 完成-- 检测 CXX 编译特性-- 检测 CXX 编译特性 - 完成-- PYTHON_EXECUTABLE 现在是:D:/dev/Pybind/cpp_google_trans2/venv/Scripts/python.exe-- ENV{PYTHONPATH} 现在是:D:/dev/Pybind/cpp_google_trans2/venv/Lib/site-packages-- PATH 现在是:D:/dev/Pybind/cpp_google_trans2/venv/Scripts/;D:/dev/Pybind/cpp_google_trans2/venv/Lib-- 找到 PythonInterp:D:/dev/Pybind/cpp_google_trans2/venv/Scripts/python.exe(找到版本3.7.3")-- 找到 PythonLibs:D:/Programs/VisualStudio/Shared/Python37_64/libs/Python37.lib-- pybind11 v2.3.dev1-- 配置完成-- 生成完成-- 构建文件已写入:D:/dev/Pybind/cpp_google_trans2/build

我也尝试通过 control panel>system and security>system>advanced system settings>advanced>environment variables 全局设置 PYTHON_EXECUTABLE 和 PATH 环境变量,但即使这样也无济于事.>

我对 cmake、python 和 pybind11 还是很陌生,我知道我不知道很多事情.也许您在阅读此主题时已经注意到这一点.;P

解决方案

解决方案包括两部分.

将 virtualenv PYTHONPATH 编译到您的 C++ 程序中
在 CMake 中,这可以通过 target_compile_definitions 来完成.自定义路径将作为预处理器宏提供.

target_compile_definitions(app PRIVATE -DCUSTOM_SYS_PATH="\"${CMAKE_HOME_DIRECTORY}/venv/Lib/site-packages\"")

更新 Python sys.path 正确启动解释器.

这是特定于 pybind 的,但应该类似于:

py::module sys = py::module::import("sys");sys.attr("path").attr("insert")(1, CUSTOM_SYS_PATH);

I am trying to make a simple c++ application which translates phrases using googletrans python library. So I've chosen pybind11 for this purpose to embed python. Also I use cmake for code configuration.

Everything works just fine when I'm using the global python installation, but I don't understand how to use virtual environment with pybind and the whole process of setting the correct python interpreter, paths etc. in cmake much.

I've found this stackoverflow thread: Embedding pybind11 with virtual environment

I set all the variables as @ipa did. Just look at the CMakeLists.txt and main.cpp:

cmake_minimum_required(VERSION 3.15)
project("cpp_google_trans")

set(
    PYTHON_EXECUTABLE "${CMAKE_HOME_DIRECTORY}/venv/Scripts/python.exe"
    CACHE FILEPATH "python virtual environment executable")
message(STATUS "PYTHON_EXECUTABLE is now: ${PYTHON_EXECUTABLE}")    #DEBUG

set(ENV{PYTHONPATH} "${CMAKE_HOME_DIRECTORY}/venv/Lib/site-packages")
message(STATUS "ENV{PYTHONPATH} is now: $ENV{PYTHONPATH}")  #DEBUG

set(
    ENV{PATH}
    "${CMAKE_HOME_DIRECTORY}/venv/Scripts/;${CMAKE_HOME_DIRECTORY}/venv/Lib"
)
message(STATUS "PATH is now: $ENV{PATH}")   #DEBUG

add_subdirectory(pybind11)

add_executable(app main.cpp)
target_link_libraries(app PRIVATE pybind11::embed)

main.cpp:

#include <iostream>
#include <string>
#include <pybind11/embed.h>
namespace py = pybind11;

int main() {
    py::scoped_interpreter guard{};

    auto sys = py::module::import("sys");
    py::print("Hello, World from Python!");
    py::print(sys.attr("executable"));
    py::print(sys.attr("version"));

    system("set PATH");

    std::cin.get();

    // system("powershell");
    // I was looking at the environment variables in the powershell, but there wasn't any variables I set in CMakeLists.txt

    // Here I get abort() when trying to import googletrans package.
    // The package is installed in the venv virtual environment.
    // When the package is installed globally there isn't any problem.
    py::object Translator = py::module::import("googletrans").attr("Translator");
    py::object translator = Translator();

    std::cout << "C++ program here!\nTell a phrase you want to translate to english: ";
    std::string phrase;
    std::getline(std::cin, phrase);

    std::cout << "\n\nThe phrase in english means: ";
    std::cout << translator.attr("translate")(py::cast(&phrase)).attr("text").cast<std::string>();
}

When looking at the cmake configuration output everything seems working well (instead of PythonLibs variable I don't know how to change):

-- Building for: Visual Studio 16 2019
-- The C compiler identification is MSVC 19.22.27812.2
-- The CXX compiler identification is MSVC 19.22.27812.2
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/VC/Tools/MSVC/14.22.27812/bin/Hostx64/x64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/VC/Tools/MSVC/14.22.27812/bin/Hostx64/x64/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/VC/Tools/MSVC/14.22.27812/bin/Hostx64/x64/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/VC/Tools/MSVC/14.22.27812/bin/Hostx64/x64/cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- PYTHON_EXECUTABLE is now: D:/dev/Pybind/cpp_google_trans2/venv/Scripts/python.exe
-- ENV{PYTHONPATH} is now: D:/dev/Pybind/cpp_google_trans2/venv/Lib/site-packages
-- PATH is now: D:/dev/Pybind/cpp_google_trans2/venv/Scripts/;D:/dev/Pybind/cpp_google_trans2/venv/Lib    
-- Found PythonInterp: D:/dev/Pybind/cpp_google_trans2/venv/Scripts/python.exe (found version "3.7.3")    
-- Found PythonLibs: D:/Programs/VisualStudio/Shared/Python37_64/libs/Python37.lib
-- pybind11 v2.3.dev1
-- Configuring done
-- Generating done
-- Build files have been written to: D:/dev/Pybind/cpp_google_trans2/build

I also tried to set PYTHON_EXECUTABLE and PATH environment variables globally through control panel>system and security>system>advanced system settings>advanced>environment variables, but even this didn't help.

I am still pretty new to cmake, python and pybind11 and I am aware of that I don't know a lot of things. And maybe you've noticed this while reading this thread. ;P

解决方案

The solution involves two parts.

Compile the virtualenv PYTHONPATH into your C++ program
In CMake, this can be done with target_compile_definitions. The custom path will be available as a preprocessor macro.

target_compile_definitions(app PRIVATE -DCUSTOM_SYS_PATH="\"${CMAKE_HOME_DIRECTORY}/venv/Lib/site-packages\"")

Update the Python sys.path right starting the interpreter.

This is pybind-specific, but ought to look something like:

py::module sys = py::module::import("sys");
sys.attr("path").attr("insert")(1, CUSTOM_SYS_PATH);

这篇关于使用 pybind11 嵌入 python.虚拟环境不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆