#2873: Simplify usage of GRASS in Python from outside
-------------------------------------------------+-------------------------
Reporter: wenzeslaus | Owner: grass-dev@…
Type: enhancement | Status: new
Priority: major | Milestone: 7.1.0
Component: Python | Version: svn-trunk
Keywords: startup, installation, scripts, | CPU: Unspecified
interpreter, windows installer, pygrass, |
temporal, bootstrap, boilerplate |
Platform: All |
-------------------------------------------------+-------------------------
To use GRASS GIS functionality in Python from outside of a GRASS session,
i.e. without starting GRASS GIS explicitly and running a script (or an
actual module) in the session, one needs to include approximately 50 lines
as described in the
[https://grass.osgeo.org/grass70/manuals/libpython/script.html#module-
script.setup grass.script.setup] manual (or in the lengthy related
[https://grasswiki.osgeo.org/wiki/Working_with_GRASS_without_starting_it_explicitly
wiki page]).
Ideally, one would just do import and then one or two lines of
initialization, for example:
{{{
#!python
import grass.script as gscript
rcfile = gscript.init_data("~/grassdata", "nc_spm", "user1")
do_what_ever_with_grass()
os.remove(rcfile)
}}}
== Suggestion ==
The attached code is a prototype implementation of the Python part which
would allow something like this. The code can only work if the following
variables are set:
{{{
#!bash
export GRASS_EXECUTABLE="/path/to/grass"
export LD_LIBRARY_PATH=$($GRASS_EXECUTABLE --config path)/lib
export PYTHONPATH=$($GRASS_EXECUTABLE --config path)/etc/python
}}}
The `GRASS_EXECUTABLE` does not have to be set if `grass` is on the path
or, in theory, if it is in on some standard path (e.g. `C:\Program Files
(x86)\GRASS GIS 7.0.0\grass70.bat` on MS Windows). However, dynamic
library path must always be set ahead (as described in #2424) for ctypes
to work (both PyGRASS and temporal depends on ctypes). The path to Python
packages must be set ahead as well if you want to use the initialization
functions from the package.
== Making it simple ==
The three lines above might be good enough on Linux where you just dump it
to command line or `.bashrc` but for MS Windows users it is too
complicated. The QGIS project also considers this too much work
([https://github.com/qgis/qgis3.0_api/issues/9 PyQGIS bootstrap is
complicated]).
GRASS Python packages could go to the system packages directory, so that
we avoid the need for setting `PYTHONPATH`. This might work well on MS
Windows when usage of system Python is implemented as described in #2333.
On Linux, `LD_LIBRARY_PATH` can be avoided if the libraries are installed
into the system path. On MS Windows, putting more things on `PATH` is
standard procedure from what I have seen. Mac OS X, `DYLD_LIBRARY_PATH`
can't be used anyway [https://lists.osgeo.org/pipermail/grass-
dev/2016-January/078531.html since El Capitan].
GRASS GIS executable should be on path on all platforms in the same way as
it is on path in Linux. This is maybe not standard on MS Windows but at
the end this is what users want (they want GRASS to be available right
away).
== Challenges ==
When putting dynamic libraries and Python packages directly into system
paths, installing more than one GRASS version becomes more complicated.
However, that's OK because only advanced users would have more than one
version, so the hard work of making it work (perhaps just not using the
default settings in the installer) will be on them. Beginners will likely
have just one version. The exception might be on MS Windows where it is
possible that beginner has standalone GRASS GIS, the one from QGIS and one
from OSGeo4W.
GRASS Python packages are not prepared to be imported when `GISBASE` is
not set and may require even more. We would need to change the code to not
require anything from GRASS session at import time. So far, I needed to
add lazy initialization for the translate function (underscore) to be able
to import `grass.script.core` (patch attached).
There is already some duplication between `grass.script.setup` and
`grass.py` executable. To create a full session (e.g. Mapset locking) we
would need even more duplication. We could move some parts from `grass.py`
to `grass.script.setup` if we are sure that we can import the right
`grass.script.setup` during the initialization phase (we already rely on
in when creating a Location).
--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2873>
GRASS GIS <https://grass.osgeo.org>