Calling Python from C++ and accessing packages installed via Anaconda

Viewed 1127

I've developed some Python code to model a thermal device from within my base Anaconda environment. This code uses some packages, such as numpy, which were installed to that environment.

I would like to interface this code with a commercial thermal system modeling program on the same workstation (MS Windows 10 OS). The program/Python interface is handled through some C++ code compiled into a DLL. A simplified snippet looks like:

#include <Python.h>
scriptName = "PyScript"
functionName = "InterfaceFunction"

Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("import os");
PyRun_SimpleString("sys.path.append(os.getcwd())");

pName = PyUnicode_DecodeFSDefault(scriptName.c_str());
pModule = PyImport_Import(pName); // Here's where things go bad.
pFunc = PyObject_GetAttrString(pModule, functionName.c_str());
pValue = PyObject_CallObject(pFunc, NULL);

The interface works for calling a function in a simple Python script that uses only built-in Python functionality. However, the real code that I want to run requires a few import statements for several of the aforementioned packages installed to the base Anaconda environment. Attempting to import any of those results in a failed call when loading the script. Specifically, the statement pModule = PyImport_Import(pName) results in pModule == 'NULL' being true.

I've already included my key Anaconda environment directories in the PYTHONPATH system environment variable, including:

C:\ProgramData\Anaconda3
C:\ProgramData\Anaconda3\DLLs
C:\ProgramData\Anaconda3\Lib
C:\ProgramData\Anaconda3D\Lib\site-packages

I have also tried launching the calling program from a CMD.exe window after executing the activate.bat base command, but the package imports still cause failure.

Is there any way to either activate my Anaconda base environment for the calling process in the C++ code prior to the PyImport_Import() call to get modules to properly import? Or am I just stuck needing to drop Anaconda's environments and freshly install python and all the needed modules without using environments?

1 Answers

If you are trying to run a python script within conda using the base environment, try something this, replacing the -V with your python script:

conda run -n base python -V

Python 3.7.6

from within C++, if you are able to run a python script, you can try this:

import subprocess
subprocess.run('c:\\Users\\iowahawk89\\miniconda3\\condabin\\conda.bat activate base && "c:\\Users\\iowahawk89\\miniconda3\\Scripts\\conda.exe" "list" && conda deactivate', shell=True)

subprocess.run('c:\\Users\\iowahawk89\\miniconda3\\Scripts\\conda.exe run -n base python hello.py', shell=True)

or if you want to run python in the interpreter directly, you can try this:

subprocess.run('c:\\Users\\iowahawk89\\miniconda3\\Scripts\\conda.exe run -n base python -V', shell=True)

other ideas:

subprocess.run('c:\\Users\\iowahawk89\\miniconda3\\Scripts\\conda.exe run -n base python -V', shell=True)

subprocess.run('c:\\Users\\iowahawk89\\miniconda3\\Scripts\\conda.exe run -n base python hello.py', shell=True)

save the output for use later

output = subprocess.check_output(['c:\\Users\\iowahawk89\\miniconda3\\Scripts\\conda.exe', 'list', '-n', 'base'])
print('Have %d bytes in output' % len(output))
print(output)

output = subprocess.check_output(['c:\\Users\\iowahawk89\\miniconda3\\condabin\\conda.bat', 'activate', 'base'], shell=True)

In all cases, i am able to see the correct python version from my conda environment.

Related