CPython is what most people consider regular Python. If you have used Python before on your computer, then you were most likely using CPython. We refer to it as CPython in the documentation for clarity.
Python is a programming language. The Python language has several different implementations, or variants. Two Python implementations are supported by RiskScape:
Jython: the default Python support in RiskScape.
CPython: the Python that you typically use outside of RiskScape.
As soon as you try to
import Python modules into your RiskScape function,
you will notice that Jython behaves quite differently to regular Python.
To make life easier, RiskScape lets you write RiskScape functions that use the exact same
Python installation that you use normally.
To use CPython functions in RiskScape, you must have Python already installed locally on your system.
Configuring CPython support in RiskScape
Normally when you run Python code outside of RiskScape, you will be using
python binary (Linux or Mac) or a
python.exe executable (Windows) that is installed somewhere on your system.
In order to use CPython in RiskScape, you have to first tell RiskScape where this Python binary is located.
We do this by specifying full path to the Python binary in RiskScape’s
Refer to the Settings file instructions for where
settings.ini is located on your system.
You may need to create the
settings.ini file if it does not already exist.
On Windows, you can do this by entering the following commands into your terminal:
mkdir %USERPROFILE%\RiskScape notepad %USERPROFILE%\RiskScape\settings.ini
Next, you will need to add a
[cpython] configuration section and specify the
python3-bin path to the Python binary.
On Windows, a typical
settings.ini might look something like this:
[cpython] python3-bin = C:\Users\Ronnie\AppData\Local\Python\Python 3.8\python.exe
python3-bin path will vary depending on where Python was installed on your system.
If you are not sure where Python is installed on your system, try running the following command:
which python(Linux or Mac)
If you use several different Python environments (i.e.
venv), then each virtual environment will have its own Python executable.
You will need to activate the Python environment you want to use first, before running
For example, if you use the Anaconda Python distribution
the default Python location might look like
Whereas the path for a Python environment called
Geo would look more like
On Linux or Mac, the
settings.ini file will look more like the following (note that the path may vary).
[cpython] python3-bin = /usr/bin/python3
You can test your installation by running
If any warnings or errors occur, then you may have specified the incorrect
python3-bin file path.
Try following the Troubleshooting section below.
Writing CPython functions for RiskScape
There is no special magic required to make your functions work with RiskScape, but there are a few important points to know.
You must have a function in your script called
function- this is the one that RiskScape will call.
importa Python package in your RiskScape function, you must first have that CPython package installed locally. Refer to python.org for more details on how to install a Python package.
Data is passed to CPython in simple JSON-like data types; it will be a mixture of numbers, strings, lists and dictionaries. Trying to use more complicated data types, like coverages or lookup tables, will fail.
You can use
Your function will get called for every element-at-risk, so adding
riskscape model run commands.
We recommend only using
riskscape expression evaluate, or with a small
sub-set of model data.
You can test your functions with and without RiskScape. You could use a separate python script that imports and tests your CPython RiskScape function script, or you can test it in RiskScape using the
riskscape expression evaluatecommand.
For more efficient model processing with CPython, it can be worth defining the type that your function uses. A lot of the examples will simply use
argument-types = [ building: anything, hazard: nullable(floating) ]. However, this can be inefficient because the
anythingtype will pass all the exposure-layer data to your function, regardless of whether the function uses it or not.
Not all data types are supported with CPython. For example,
datetypes are currently not supported. This will result in an error if your exposure-layer data contains these types. You can avoid this problem by defining the exact type that your function expects, instead of
A Simple example
To start with we’ll create a simple hello world python function. Create a
helloworld.py file in
your favourite text editor and add the following:
def function(name): return "Hello, %s" % name
In the same directory, create a
project.ini and add the following:
[function helloworld] framework = cpython location = helloworld.py return-type = text argument-types = [text]
Now, in the same directory, open a terminal or command prompt and test your function with the following command:
riskscape expression eval "helloworld('Ronnie')"
If it has worked successfully, you should see:
Fortunately, CPython integration is not limited to just “Hello, world” examples.
Using Geometry in your CPython functions
RiskScape supports passing geometry to your CPython function, but there are some important things you will need to know if you want to manipulate geometry in your Python code.
There are many Python packages available for working with geometry. RiskScape can’t predict what specific geometry package you will want to use, so it passes the geometry to your function in the well-known bytes format (known as WKB).
In your function, you can then construct a geometry object from the WKB. How you do this depends on what Python package you are using for geometry.
If your function also returns geometry, then you will need to return it in WKB format, rather than returning the geometry object itself.
Here is a simple example that uses the
shapely Python package to work with geometry.
The following function both takes geometry as an argument and also returns it.
# project.ini [function get_centroid] location = centroid.py framework = cpython description = Return the centroid (point) of a simple feature return-type = geometry argument-types = [geometry]
# centroid.py from shapely import wkb # returns the centroid of the feature def function(geom): # note the geometry argument gets passed as a tuple bytes, srid = geom # use shapely to turn the WKB into geometry shapely_geom = wkb.loads(bytes) # return the input geometry's centroid (as WKB) return (shapely_geom.centroid.wkb, srid)
Notice that the geometry argument is passed as a two-item tuple, containing the WKB
bytes as well as an
srid. This is because RiskScape
stores an opaque identifier, called an spatial reference identifier (SRID), to identify the coordinate reference system
the geometry belongs to.
You only need to worry about the SRID if your function’s return-type contains geometry, i.e. you want to modify the geometry yourself in Python. Returning the same SRID tells RiskScape that the coordinate reference system has not changed.
CPython vs Jython
The CPython and Jython plugins are both enabled in your RiskScape installation by default.
If you correctly setup CPython in your
settings.ini, any Python functions
in your project will be executed using CPython by default.
Otherwise, Jython will be used by default.
In your INI file, you can explicitly define what Python implementation RiskScape should use
framework parameter, like we did in our
helloworld example earlier.
This makes it possible to use a mix of both Jython (i.e.
framework = jython) and
framework = cpython) functions in your project.
Whether you use CPython or Jython will depend on your circumstances. Using CPython requires extra setup, as you need to have a pre-existing working python environment available, but it gives you access to a complete and familiar python environment.
Jython requires no setup, but is limited to python 2.7 and is geared towards scripting a Java environment, rather than being a true python environment. For simple functions this isn’t a problem.
If you have never used Python before, and only want to write a simple risk function,
then we recommend using Jython. If you want to use other Python modules, such as
then you should use CPython.
First, check the
python3-bin path in your
settings.ini is a valid Python 3 executable
python -V command.
RiskScape only supports Python 3. If you see a
2.x.x version displayed, then you will need
to install Python 3.
You may also want to check your version of Python 3 is still supported.
Older, unsupported versions of Python 3 may still fail to work with RiskScape due to compatibility issues.
RiskScape is known to work with Python v3.8 and v3.9.
Next, check that you can use your
python.exe path to execute a simple Python statement, e.g.
C:\Your\Path\To\Python\python.exe -c "print(1 + 1)" 2
If you see an error instead of
2, it may mean you are using the wrong
python.exe path, or you need to
install a more recent version of Python on your system.
For example, a bad Python install might throw out a cryptic error like:
C:\Your\Path\To\Python\python.exe -c "print(1 + 1)" ImportError: No module named site
Finally, if that all works, check that all the
settings.ini keywords are all lower-case, and RiskScape is loading the correct
The following command will display debug containing the
settings.ini and CPython path.
riskscape --log-level .engine.cli.CliBootstrap=info,.cpython=info --version
You could also double-check the INI file definition for your function. If it contains the
then check it’s set to the Python implementation that you want to use, i.e.