Python (pip) packaging the software based on ROOT + PyROOT


Please read tips for efficient and successful posting and posting code

ROOT Version: 6.26
Platform: Ubuntu 20.04
Compiler: GCC 10.3


So I have a C++ shared library built using CMake which extensively uses ROOT, its data structures and visualization tools. This library handles all the performance critical low level analysis routines (Lets call it library.so). The code has directory structure of typical of CMake project.
Then I made a PyROOT based higher level interface in python and it is all working nicely. However
the PyROOT based interface will probably keep expanding (it is already fairly large) and it is now important for me to divide it into python modules and properly package it. Currently each python module
imports the ROOT, and loads the C++ library using gSystem.Load(“library.so”) and all the python modules (basically *.py files) reside in ‘bin’ directory. The path to library.so is provided through a specially created environment variable. But I would like the python part of the software to have typical python package structure. In that case how do I autoload ‘library.so’ in each python submodule ?
If I place, the library.so to the ROOT library path, will PyROOT autoload it ?
My directory structure currently looks like

Software
|-- CMakeLists.txt // this file builds the library.so
|-- build/  // This is where CMake builds 
|-- lib/ // The library.so is placed here
|-- src/ // all the C++ source files distributed in subfolders
|-- include/ // all the C++ headers 
|-- bin/ // all C++ executables + python source files + python executables 

I think @etejedor can help.

Hello,

You need to load your library from your PyROOT scripts in order to use it, it won’t be loaded automatically. Since you know you have that structure, what you can do is refer to the ../lib directory relatively from the directory where your Python sources are placed. Something like:

import os 
dir_path = os.path.dirname(os.path.realpath(__file__))

and then navigate from there.

Thanks for quick reply.
I want to install the python part of the software using setuptools so that it can be accessed from anywhere and it can be imported like any other python module. This I was planning to do by running
‘setup.py install’ as custom_coomand of CMake at the end. However, in that case, python modules will not be in ‘bin’ directory after running setup.py.

Hello,

Then if you need your library.so for your Python modules to work, and you will install such modules in standard Python directories, you can also make sure the library.so is installed together with your Python modules. It is common to see libraries that install their C extension modules together with their Python layer.

Writing C extensions is very lengthy work, which I want to avoid.
Also I don’t require it as such. I think I have explained my requirement wrongly.
I have some “pure python” modules which work as high level interface. These modules
make use of CMake built C++ library.so and ROOT. The library.so itself is generated via rootcling
and has all the TObject derived classes. library.so is loaded into python modules by simply

import ROOT
os.environ.get(libpath,"ANASYS")
ROOT.gSystem.Load(os.paths.join(libpath,"library.so"))

By this way, I don’t really need python C extension wrappers for library.so.
The library.so need not be exposed to the code user. It just needs to be
loaded successfully independent of installation location of python modules and scripts.
Currently, I am exporting some ANASYS variable so to identify location of library.so.
Now I can import my python modules without problems once I define ANASYS
variable. But I want some way, where I don’t need anything extra beyond building
library.so by CMake and installing python modules using setup.py.
If I could modify ‘import ROOT’ behaviour so as to automatically load library.so
everytime ROOT is imported, that would be the best solution. But I don’t have
that much expertise in python yet. Could there be a feature in ‘PyROOT’ which automatically
loads rootcling/REFLEX generated ROOT dictionaries, whenever ROOT is imported?

Hello,

You can still install your library.so together with the python modules, even if the library is not an extension module. Using os.path.realpath and gSystem.Load you could load the library without the need of using any environment variable. Would that make sense?

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.