How to use a virtual environment to call Python from C++ in Clion?

Viewed 1324

I would like to use a virtual environment to call Python from C++ in Clion.

I can use Py_Initialize(); on C++ when I run it on terminal, but I cannot use it when I run it on Clion.
The following is the error message when running in Clion.

Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
Fatal Python error: Py_Initialize: Unable to get the locale encoding
ModuleNotFoundError: No module named 'encodings'

Current thread 0x00007fbd24916680 (most recent call first):

On the terminal, I use GNU Make to build and run the code by entering the Anaconda virtual environment. Then the code works as expected.

On the other hand, on Clion, I thought that if I set up the Anaconda virtual environment in Python Interpreter from File/Build, Execution, Deployment/Python Interpreter/, it would be referenced at runtime. However, it seems that the reference is not working properly and the above error occurred. The above error also occurred when I ran the code in the terminal without entering the virtual environment.

Does anyone know how to set this up?
Thank you.

== Aditional part ==
This is CMakeList.txt

cmake_minimum_required( VERSION 3.6 )
# Create Project
project( Python2CPP )

# Require C++14 (or Later)
set( CMAKE_CXX_STANDARD 14)
set( CMAKE_CXX_STANDARD_REQUIRED ON )

find_package(OpenCV REQUIRED)

add_definitions("-DNOMINMAX")

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

add_executable( 
    Python2CPP
    src/main.cpp
    src/Python2CPP.cpp
    src/Python2CPP.h )

set_property( DIRECTORY PROPERTY VS_STARTUP_PROJECT "Python2CPP" )

# virtual python env from anaconda
set(PYTHON_INCLUDE_DIRS /home/masahiro/anaconda3/envs/virt/include/python3.6m)
set(NUMPY_INCLUDE_DIRS /home/masahiro/anaconda3/envs/virt/lib/python3.6/site-packages/numpy/core/include)
set(PYTHON_LIBRARIES /home/masahiro/anaconda3/envs/virt/lib/libpython3.6m.so)

include_directories(
    ${PYTHON_INCLUDE_DIRS}
    ${NUMPY_INCLUDE_DIRS}
    ${OpenCV_INCLUDE_DIRS})

target_link_libraries(
    Python2CPP
    ${PYTHON_LIBRARIES}
    ${OpenCV_LIBS}
)

1 Answers

I have reworked your CMakeLists.txt to use the standard way of finding the Python interpreter and Python libraries. Can you give it go? If you have CMake 3.14 or higher then the ability to find NumPy is already built in.

cmake_minimum_required( VERSION 3.14 )
# Create Project
project( Python2CPP )

# Require C++14 (or Later)
set( CMAKE_CXX_STANDARD 14)
set( CMAKE_CXX_STANDARD_REQUIRED ON )

find_package(Python3 COMPONENTS Interpreter Development NumPy REQUIRED)
find_package(OpenCV REQUIRED)

add_definitions("-DNOMINMAX")

add_executable(
    Python2CPP
    src/main.cpp
    src/Python2CPP.cpp
    src/Python2CPP.h)

set_property( DIRECTORY PROPERTY VS_STARTUP_PROJECT "Python2CPP" )

target_include_directories(Python2CPP PRIVATE ${Python3_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} ${Python3_NumPy_INCLUDE_DIRS})

target_link_libraries(Python2CPP PRIVATE ${Python3_LIBRARIES} ${OpenCV_LIBS})

Otherwise, if you have older version of CMake, then you can add a test to check whether NumPy is available:

cmake_minimum_required( VERSION 3.6 )
# Create Project
project( Python2CPP )

# Require C++14 (or Later)
set( CMAKE_CXX_STANDARD 14)
set( CMAKE_CXX_STANDARD_REQUIRED ON )

find_package(PythonInterp REQUIRED)
find_package(PythonLibs ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} EXACT REQUIRED)

find_package(OpenCV REQUIRED)

# Find NumPy location
execute_process(
        COMMAND
        ${PYTHON_EXECUTABLE} "-c" "import re, numpy; print(re.compile('/__init__.py.*').sub('',numpy.__file__))"
        RESULT_VARIABLE _numpy_status
        OUTPUT_VARIABLE _numpy_location
        ERROR_QUIET
        OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT _numpy_status)
    set(NumPy ${_numpy_location} CACHE STRING "Location of NumPy")
endif()

# Find NumPy version
execute_process(
        COMMAND
        ${PYTHON_EXECUTABLE} "-c" "import numpy; print(numpy.__version__)"
        OUTPUT_VARIABLE _numpy_version
        ERROR_QUIET
        OUTPUT_STRIP_TRAILING_WHITESPACE
)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NumPy
        FOUND_VAR NumPy_FOUND
        REQUIRED_VARS NumPy
        VERSION_VAR _numpy_version)

add_definitions("-DNOMINMAX")

add_executable( 
    Python2CPP
    src/main.cpp
    src/Python2CPP.cpp
    src/Python2CPP.h )

set_property( DIRECTORY PROPERTY VS_STARTUP_PROJECT "Python2CPP" )

target_include_directories(Python2CPP PRIVATE ${PYTHON_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS})

target_link_libraries(Python2CPP PRIVATE ${PYTHON_LIBRARIES} ${OpenCV_LIBS})

Python virtual environment

Before building your C++ program, activate your Python virtual environment. If you're using CLion, it has Terminal tab. Select that and activate your virtual environment like this: source <virtual environment path>/bin/activate. Then cmake should find the correct Python interpreter.

Related