Python and GRASS GIS

Python is one of the world's most popular programming languages. It is not only very popular in science but also the field of GIS. Python is easy to work with and supports you in simple as well as complex tasks due to the huge amount of high level libraries available including machine learning and more.

GRASS GIS provides a Python API (see also the related page collection in the GRASS GIS Wiki to all functionality. More that 70 of the GRASS GIS modules are written in Python; they are a good starting point to see how that's done (including graphical user interface generated automatically, command line interface, XML self-description, multi-language support etc. etc.)

Now, sometimes you do not want to use Python within a GRASS GIS session but simply use the wealth of functionality from "outside", that is using GRASS GIS as your backend for geospatial number crunching.

Usage is very simple.

The requirements

The requirements are:

  • GRASS GIS 7.6 or newer installed
    • download from here
  • "grass-session" installed:
    • pip install grass-session

Using "grass-session" to access GRASS GIS functionality from Python

In a first step we define a few settings:

# define where to process the data in the temporary grass-session
mygisdb = '/tmp/grassdata'
mylocation = 'world'
mymapset = 'user'

Next we import "grass-session":

# the next line starts the GRASS GIS session
from grass_session import Session

It is also a good idea to import some further parts of the GRASS GIS Python API:

# import some convenient GRASS GIS Python API parts
from grass.script import core as gcore
import grass.script as gscript
import grass.script.setup as gsetup
# import grass python libraries
from grass.pygrass.modules.shortcuts import general as g
from grass.pygrass.modules.shortcuts import raster as r
from grass.pygrass.modules.shortcuts import vector as v
from grass.pygrass.modules.shortcuts import temporal as t

# set some common environmental variables, like for raster compression settings:
import os
os.environ.update(dict(GRASS_COMPRESS_NULLS='1'))
#  needs G76:          GRASS_COMPRESSOR='ZSTD'))

Now we can define and create a session instance:

# create a PERMANENT mapset object: create a Session instance
PERMANENT = Session()

This session we open now, defining the projection parameters e.g. using the EPSG code (alternative: use raster or vector file with metadata):

# hint: EPSG code lookup: https://epsg.io
PERMANENT.open(gisdb=mygisdb, location=mylocation,
               create_opts='EPSG:4326')

This PERMANENT mapset we keep and close it (it could be used later on to store base cartography):

# exit from PERMANENT right away in order to perform analysis in our own mapset
PERMANENT.close()

Now we open a new session with a user mapset, for own results:

# create a new mapset in the same location
user = Session()
user.open(gisdb=mygisdb, location=mylocation, mapset=mymapset,
               create_opts='')

The session is open and some GRASS GIS commands can now be run inside this user mapset. An an example, we download and import country maps from naturalearthdata.com including a topological vector data cleaning on the fly:

# import admin0 vector data - it downloads and imports including topological cleaning on the fly
#   Data source: https://www.naturalearthdata.com/downloads/10m-cultural-vectors/
#   VSI driver for remote access: http://www.gdal.org/gdal_virtual_file_systems.html#gdal_virtual_file_systems_vsicurl
inputfile = "/vsizip/vsicurl/https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_0_countries.zip"

# note the pythonic underscore (we could also use v.import)
v.in_ogr(input=inputfile, output="countries", overwrite = True)

Let's look at the metadata of the imported vector map:

# show the attribute column names
v.info(map="countries", flags="c")
# list vector maps available in the current mapset
g.list(type="vector", flags="m")

Now do further geospatial processing or anaylsis with the map... Optionally export the result with v.out.ogr or r.out.gdal.

Eventually we close the active session:

# exit from user mapset (the data will remain)
user.close()

The location/mapset remain but could be deleted if no longer needed.

Download the 'grass_session_vector_import.py' script as a single file.

Enjoy!