Python bindings
This document describes different ways to add Python bindings to a given
DUNE setup. The description is for DUNE 2.8+. For the 2.7 release the steps
are very similar except that an additional module
dune-python
is required containing the scripts described below, i.e., instead of
dune-common/bin/setup-dunepy.py
use dune-python/bin/setup-dunepy.py
.
Prerequisites
For details on how to build DUNE see the installation instructions.
Important: to be able to add the Python bindings to your setup it is important that all DUNE modules are configured to include the Python bindings and to build shared libraries by adding
-DDUNE_ENABLE_PYTHONBINDINGS=ON
-DBUILD_SHARED_LIBS=TRUE
to the CMAKE_FLAGS
. Instead of shared libraries enabling position
independent code (pic) can also be sufficient and is enable by default on
some systems.
The Python bindings for DUNE have been tested with Python 3.4+ It is also recommended to setup a Python virtual environment, e.g.,
python3 -m venv $HOME/dune-env --system-site-packages
source $HOME/dune-env/bin/activate
The following instructions assume that you are working in a virtual environment if you decide against doing this then add
-DPYTHON_INSTALL_LOCATION="user"
to your CMAKE_FLAGS
before building DUNE.
Another non essential but recommended CMAKE
flags to set is
-DADDITIONAL_PIP_PARAMS="-upgrade"
which adds -upgrade
to the pip
command used to install the DUNE Python
package (other flags can be added here as well). With this flag set
reinstalling the DUNE Python package will be carried out after a update
of the sources even if the version number has not changed.
Remark: Another useful option useful especially for developers is
-DDUNE_PYTHON_INSTALL_EDITABLE=TRUE
which installs the DUNE Python packages in editable mode so that changes made to the Python source code do not require a reinstallation of the Python package.
Installing the DUNE Python Package
After configuring all DUNE packages using ./dune-common/bin/dunecontrol
as described in installation instructions
there are two approaches to get Python bindings to work.
First Approach:
First run
./dune-common/bin/dunecontrol make install_python
which will install the DUNE Python namespace package by running
pip install
in the folders builddir/python
of all DUNE modules.
Before running a Python script you need to set some environment variables so that your DUNE sources are found:
# path to the DUNE source modules (colon separated list)
DUNE_CONTROL_PATH=DUNE_SOURCE_PATH
# the build dir used for `dunecontrol` (defaults to `build-cmake`)
DUNE_BUILDDIR=BUILDDIR_PATH
# location of new `dune-py` module (defaults to [virt-env-path]/.cache)
DUNE_PY_DIR=DUNEPY_PATH
# possible cmake flags to use, e.g., compiler flags (shared libs are activated by default)
DUNE_CMAKE_FLAGS=CMAKE_FLAGS
The DUNE_PY_DIR
variable points to the location where the new
dune-py
module is to be generated. The default location is
in .cache/
located either in the root folder of the virtual environment
if one is active or in the user’s home directory.
After setting these environment variables you can test the installation
by constructing a simple structured grid. Call python
and then execute
from dune.grid import structuredGrid
grid = structuredGrid([0,0],[1,1],[10,10])
print( grid.size(0) ) # should return 100
grid.plot() # requires the installation of `matplotlib`
Note that you need to make sure that the environment variables mentioned above are set before running a Python script using the DUNE namespace package. These variable are not required for the second approach.
Second Approach:
If you used dunecontrol
with a config.opts
then you can use the
same file to also build the dune-py
module by running
./dune-common/bin/setup-dunepy.py --opts=config.opts
after running dunecontrol
.
Note: at the time of writing the setup-dunepy.py
script does
not support other options available for dunecontrol
. This includes
the --builddir
option. The approach assumes that you set the builddir
in the option file by adding
BUILDDIR=BUILDDIR_PATH
You can also use the setup-dunepy.py
script to install the DUNE namespace
package so that a full build of DUNE with Python bindings can be achieved
with the following two steps:
./dune-common/bin/dunecontrol --opts=config.opts all
./dune-common/bin/setup-dunepy.py --opts=config.opts install
with for example the following (almost) minimal config.opts
file:
BUILDDIR=$HOME/dune_build
CMAKE_FLAGS="-DDUNE_ENABLE_PYTHONBINDINGS=ON \
-DCMAKE_CXX_FLAGS='-O3 -DNDEBUG' \
-DBUILD_SHARED_LIBS=TRUE \
-DADDITIONAL_PIP_PARAMS='-upgrade'
"
Note: After using setup-dunepy.sh
with the default DUNE_PY_DIR
it is not required to set the environment variables mentioned in the first
approach.
Pythonbindings for other DUNE modules
Besides the core modules other Dune modules also provide Python bindings. The summary for each module lists if Python bindings are available:
Embedded Python
The Python bindings are based on the pybind11
library. Hence they also allow to embedd Python in your Dune application.
To do so you can essentially follow the pybind11 instructions.
However, you cannot link agaist pybind11::embed
in CMake
but have to link to the Python library manuall using:
if(DUNE_ENABLE_PYTHONBINDINGS)
add_executable("application" application.cc)
target_link_dune_default_libraries("application")
target_link_libraries("application" PRVIATE Python3::Python)
endif()
Here if(DUNE_ENABLE_PYTHONBINDINGS)
prevents your application from being build
if the Python bindings are not enabled.
Notice that the Python bindings for Dune C++ types can also be used
in an embedded Python context.
Final Remark:
The just in time compilation is carried out in a newly created DUNE
module dune-py
. In the first approach mentioned above, this module is setup
and build each time the first DUNE package is imported in Python. The module will have a hard
dependency on all DUNE module found. As a consequence all these modules need to
be in a working condition, e.g., correctly configured and build. Using the second approach,
the dune-py
module is only build during the execution of the setup-dunepy.py
script.
By default the generated module will also depend on all modules found and the
script will fail if one of these module is not correctly configured. This can be avoided by
using the --module=moduleName
option (available with the 2.8 release). With this
option dune-py
will only depend on the module moduleName
and all DUNE modules moduleName
depends on.
