GRASS GIS – Getting GRASS 7.4.4 Working in Python 3

grassgrass-7.4pythonpython 3

I'm trying to get some GRASS functionality in a Python Script, specification r.series, but I'm struggling to import GRASS. I'm trying to uses the method outline on the GRASS Wiki, Working with GRASS without starting it explicitly, by using this code script.setup module but with these modification:

import os
import sys
import subprocess

# define GRASS Database
gisdb = "D:\GRASS_DB"

# specify (existing) Location and Mapset
location = "LearnGRASS"
mapset = "PERMANENT"

# path to the GRASS GIS launch script
grass7bin = r'C:\Program Files\GRASS GIS 7.4.4\grass74.bat'

# query GRASS GIS itself for its GISBASE
startcmd = [grass7bin, '--config', 'path']
try:
    p = subprocess.Popen(startcmd, shell=False,
                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
except OSError as error:
    sys.exit("ERROR: Cannot find GRASS GIS start script"
         " {cmd}: {error}".format(cmd=startcmd[0], error=error))
if p.returncode != 0:
    sys.exit("ERROR: Issues running GRASS GIS start script"
         " {cmd}: {error}".format(cmd=' '.join(startcmd), error=err))
gisbase = out.strip(os.linesep)

# set GISBASE environment variable
os.environ['GISBASE'] = gisbase

# define GRASS-Python environment
grass_pydir = os.path.join(gisbase, "etc", "python")
sys.path.append(grass_pydir)

# import (some) GRASS Python bindings
import grass.script as gscript
import grass.script.setup as gsetup

# launch session
rcfile = gsetup.init(gisbase, gisdb, location, mapset)

# example calls
gscript.message('Current GRASS GIS 7 environment:')
print(gscript.gisenv())

gscript.message('Available raster maps:')
for rast in gscript.list_strings(type='raster'):
    print(rast)

gscript.message('Available vector maps:')
for vect in gscript.list_strings(type='vector'):
    print(vect)

# delete the rcfile
os.remove(rcfile)

However, I am getting this error message:

Traceback (most recent call last):
File "D:/Training/LearnGRASS/LearnGRASS_7.py", line 28, in
gisbase = out.strip(os.linesep)
TypeError: a bytes-like object is required, not 'str'

It apppead that the offend line was this one:

gisbase = out.strip(os.linesep)

where the script is trying to remove the endline characters from out, so I modified the line to:

gisbaseStr = str(out).replace("\\n'", "").replace("b'", "")
gisbase = str.encode(gisbaseStr)

However, that return the error message:

Traceback (most recent call last):
File "D:/Training/LearnGRASS/LearnGRASS_7.py", line 34, in
os.environ['GISBASE'] = gisbase
File "C:\Users\bradl\Anaconda2\envs\GeoSpatial_3.6\lib\os.py", line 674, in setitem
value = self.encodevalue(value)
File "C:\Users\bradl\Anaconda2\envs\GeoSpatial_3.6\lib\os.py", line 730, in check_str
raise TypeError("str expected, not %s" % type(value).name)
TypeError: str expected, not bytes

But leaving it as a string kick up different Error Message:

Traceback (most recent call last): File "C:\Program Files\GRASS GIS 7.4.4\etc\python\grass\script\core.py", line 39, in
import builtin ModuleNotFoundError: No module named 'builtin'

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File
"D:/Training/LearnGRASS/LearnGRASS_7.py", line 41, in
import grass.script as gscript File "C:\Program Files\GRASS GIS 7.4.4\etc\python\grass\script__init__.py", line 5, in
from .core import * File "C:\Program Files\GRASS GIS 7.4.4\etc\python\grass\script\core.py", line 44, in
from os import environb as environ ImportError: cannot import name 'environb'

Best Answer

Please switch to GRASS GIS 7.7 if you need Python3 support. A lot of effort has already been invested here (which will not be backported to older versions).

You will save plenty of time (and not reinvent the wheel) when switching to GRASS GIS 7.7+. Details are found at https://trac.osgeo.org/grass/wiki/Python3Support

Edit: Since yesterday there are ready-to-use WinGRASS7.7 binaries available, see here (and here).

Edit Sep 2019:

GRASS GIS 7.8.0 with Python 3 support as been released:

GRASS GIS with Python 3 logo

Related Question