5

I would like to use some GRASS functionality from a Python programme. With GRASS 6 this required the set up of various environment variables, as detailed in the GRASS Wiki.

I am trying a similar setup with GRASS 7, as in this example:

import os

os.environ['LC_ALL'] = "en_GB.UTF-8"
os.environ['GISBASE'] = "/usr/lib/grass70/"
os.environ['PATH'] = "$PATH:/usr/bin:$GISBASE/bin:$GISBASE/scripts"
os.environ['LD_LIBRARY_PATH'] = "$LD_LIBRARY_PATH:$GISBASE/lib"
# for parallel session management, we use process ID (PID) as lock file number:
os.environ['GIS_LOCK'] = "$$"
# path to GRASS settings file
os.environ['GISRC'] = "$HOME/.grass7"
os.environ['PYTHONPATH'] = "$PYTHONPATH:$GISBASE/etc/python"

import grass.script as grass
env = grass.gisenv()
print env
#List all environment variables
for key, value in os.environ.items(): print key, value 
#Print region extent
r = grass.read_command("g.region", flags='p' )
print r

But the end result is an ImportError:

Traceback (most recent call last):
  File "grass_test.py", line 13, in <module>
    import grass.script as grass
ImportError: No module named grass.script

The basic sanity check shows the script library in the expected folder:

$ ls -la /usr/lib/grass70/etc/python/grass
total 44
drwxr-xr-x 9 root root 4096 Mai  3 08:44 .
drwxr-xr-x 3 root root 4096 Jan  7 08:16 ..
drwxr-xr-x 2 root root 4096 Mai  3 08:44 exceptions
drwxr-xr-x 2 root root 4096 Mai  3 08:44 imaging
-rw-r--r-- 1 root root  151 Mai  1 21:46 __init__.py
-rw-r--r-- 1 root root  363 Mai  3 08:44 __init__.pyc
drwxr-xr-x 2 root root 4096 Mai  3 08:44 lib
drwxr-xr-x 2 root root 4096 Mai  3 08:44 pydispatch
drwxr-xr-x 9 root root 4096 Mai  3 08:44 pygrass
drwxr-xr-x 2 root root 4096 Mai  3 08:44 script
drwxr-xr-x 2 root root 4096 Mai  3 08:44 temporal

What else must be added to this environment setup?

Update: I tried the setup suggested by Gene, but it produces the same ImportError exception:

import os

os.environ['GISBASE'] = "/usr/lib/grass70/"
os.environ['PYTHONPATH'] = "${PYTHONPATH}:$GISBASE/etc/python/"
os.environ['LD_LIBRARY_PATH'] = "$LD_LIBRARY_PATH:$GISBASE/lib"
os.environ['GIS_LOCK'] = "$$"
os.environ['GISRC'] = "$HOME/.grass7/rc"

import grass.script as grass
4

I use this

export GISBASE="path_to_your GISBASE"
export PYTHONPATH="${PYTHONPATH}:$GISBASE/etc/python/"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$GISBASE/lib"
export GIS_LOCK=$$
export GISRC="/path_to/.grass7/rc"

Then with Python

import grass.script.setup as gsetup
gisbase = os.environ['GISBASE']
gisdb="path_to_your_GISDBASE"
location="Geol"
mapset="test"
gsetup.init(gisbase, gisdb, location, mapset)
import grass.script as grass
# region extent
d = grass.parse_command('g.region', flags='p')
# d is a Python dictionary
print d
{'ellipsoid:  international': None, 'zone: ': None, 'east:       231750.54768451': None, 'cols:       456': None, 'nsres:      10.0010371': None, 'north:      125744.93437974': None, 'rows:       302': None, 'projection: 99 (Lambert Conformal Conic)': None, 'west:       227192.86784828': None, 'cells:      137712': None, 'ewres:      9.99491192': None, 'datum:      bel72': None, 'south:      122724.62117483': None}

But it is easier with the new PyGRASS

from grass.pygrass.gis.region import Region
reg = Region()
print reg.items
[(u'proj', 99), (u'zone', 0), (u'north', 125744.93437974), (u'south', 122724.62117483), (u'west', 227192.86784828), (u'east', 231750.54768451), (u'top', 284.0), (u'bottom', 156.0), (u'nsres', 10.001037102351026), (u'ewres', 9.994911921557025), (u'tbres', 1.0), (u'rows', 302), (u'cols', 456), (u'cells', 137712)]
print reg.keys()
[u'proj', u'zone', u'north', u'south', u'west', u'east', u'top', u'bottom', u'nsres', u'ewres', u'tbres', u'rows', u'cols', u'cells']
print reg.east
231750.547685
....
print reg.get_bbox()
Bbox(125744.93438, 122724.621175, 231750.547685, 227192.867848)
3
  • This setup does not work either, please check the answer for the complete code. Good advice on pyGRASS in any case. – Luís de Sousa Jun 16 '16 at 7:23
  • Another thing: executing this script with Python 3 I get a different exception, the same exception reported in this question. – Luís de Sousa Jun 16 '16 at 14:02
  • the Python version of GRASS GIS is 2.7.x and not 3.x – gene Jun 16 '16 at 15:38
3

Once a python script is running, changes to environment variables are no longer effective. They are set up right before runtime and the interpretor will not update them afterwards. PYTHONPATH can be updated using the method sys.path.append() and that is all.

A workaround is to re-execute the script after setting up the environment. This way the interpreter reloads the environment before starting up the script the second time:

import os, sys

if 'LD_LIBRARY_PATH' not in os.environ:
    os.environ['GISBASE'] = "/usr/lib/grass70"
    sys.path.append(os.environ['GISBASE'] + "/etc/python/")
    os.environ["LD_LIBRARY_PATH"] = os.environ['GISBASE'] + "/lib"
    os.environ['GIS_LOCK'] = "$$"
    os.environ['GISRC'] = os.environ["HOME"] + "/.grass7/rc"
    try:
        os.execv(sys.argv[0], sys.argv)
    except Exception, exc:
        print 'Failed re-exec:', exc
        sys.exit(1)

import grass.script as grass
1

Now there is also a module under development that simplifies the process. See:

https://grasswiki.osgeo.org/wiki/Working_with_GRASS_without_starting_it_explicitly#Python:_GRASS_GIS_7_with_an_external_library:_grass-session

or

https://github.com/zarch/grass-session

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.