GRASS GIS – Connecting Python Script External to GRASS GIS 7 Program in Windows 10

grassgrass-7.0grass.scriptpythonpython-2.7

I've tried to find resources online to link and run my Python script externally from Grass GIS 7, however, I have not been successful. I found resources here that provide instructions (e.g., https://grasswiki.osgeo.org/wiki/GRASS_and_Python#MS-Windows), but this is my first time using Python, and I haven't been able to figure it out. I am using Grass GIS 7.0.4, iPython 3.5, and Windows 10.

I tried to set environment variables in iPython and IDLE (don't know if it matters which I use to link it with Grass) with the following code:

import os
import sys

gisbase = os.environ['GISBASE'] = 'C:\OSGeo4W\apps\grass\grass-7.0.4'  #GISBASE needs to point the root of the GRASS installation directory
gisrc = 'GISRC= C:\Documents and Settings\Suzaku1\.grassrc6'
gisdbase = 'C:\Users\Suzaku1\Documents\grassdata'
location = 'demolocation'
mapset = 'PERMANENT'
LD_LIBRARY_PATH = 'C:\OSGeo4W\apps\grass\grass-7.0.4\lib'
PATH = 'C:\OSGeo4W\apps\grass\grass-7.0.4\etc';'C:\OSGeo4W\apps\grass\grass-7.0.4\etc\python';'C:\OSGeo4W\apps\grass\grass-7.0.4\lib';'C:\OSGeo4W\apps\grass\grass-7.0.4\bin';'C:\Python27';'C:\OSGeo4W\apps\Python27';'C:\OSGeo4W\apps\grass\grass-7.0.4\scripts';'C:\OSGeo4W\bin';'C:\OSGeo4W\apps\Python27\Lib\site-packages'
PYTHONLIB = 'C:\Python27'
PYTHONPATH = 'C:\OSGeo4W\apps\grass\grass-7.0.4\etc\python'
GRASS_SH = 'C:\OSGeo4W\apps\msys\bin\sh.exe'

sys.path.append(os.path.join(os.environ['GISBASE'], 'etc', 'python'))

import grass.script as grass

The gisrc variable links to a text document I created following the recommendation here (see Update#2). I saved the text file as 'grass.pth' and placed it in (C:\OSGeo4W\apps\python27\lib\site-packages). Not sure if my gisrc variable is correct here since it doesn't link to the location referenced in the code above: Problem with python script to control GRASS GIS from outside – How to import grass.script under Win 8.1?

When I run the code, I receive an error saying that, 'import grass.script as grass' importerror: no module named grass.script'.

What am I doing wrong?

I have iPython (v3.5) installed via Anaconda and a separate installation of Python that was provided with the Grass GIS 7 download (v2.7). Not sure if this matters for linking.

Best Answer

The linked says you need to set environmental variables. This is done in Python using e.g.:

import os
os.environ['GISBASE'] = "/some/path"

The syntax

PYTHONPATH = 'C:\OSGeo4W\apps\grass\grass-7.0.4\etc\python'

in Python just sets a variable (global one in your case) which is just a Python variable, nothing more, nothing less. The aforementioned wiki just lists the environmental variables to be set. How you set them is up to you. You can do it ahead in the command line before starting Python, you can change it in the system (search the Internet for how to do it in some GUI for your version of MS Windows), or you can use Python (os.environ).

Here is an example how to setup the environment (simplified from GRASS Python doc):

import os
import sys
import subprocess

grass7bin = r'C:\Program Files\GRASS GIS 7.0.4\grass70.bat'
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)

os.environ['GISBASE'] = gisbase
grass_pydir = os.path.join(gisbase, "etc", "python")
sys.path.append(grass_pydir)

import grass.script.setup as gsetup

gisdb = os.path.join(os.path.expanduser("~"), "Documents/grassdata")
location = "nc_spm_08"
mapset = "user1"

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

# use grass functions here

os.remove(rcfile)

Now you put your GRASS module calls and GRASS Python API function calls to the place where # use grass functions here is.

Note that you don't do anything from the above if you just run the code from inside GRASS GIS session. However, the code once you have the environment done in the right way is the same and looks for example like this:

import grass.script as gscript

gscript.run_command('g.region', s=10, n=50, w=30, e=60, res=2)
gscript.mapcalc('test1 = sin(col() + row())')
print gscript.read_command('r.info', map='test1', flags='g')
print gscript.parse_command('r.univar', map='test1', flags='g')
Related Question