فهرست منبع

init: Output value for sys.path in config (#1835)

With this addition, running grass --config python_path outputs the value needed for sys.path. This is useful in Python
where sys.path needs to be set up correctly before the grass package can be imported.

Instead of having to hardcode the etc/python part of the path, user can (optionally) obtain the full path from the new
parameter resulting in a more general code which requires just passing a result of call stripped from the white spaces.

This is especially interesting in combination with #1838 after which GISBASE environmental variable does not have to be
set up before for importing grass.script package, so setting up sys.path is the only step user needs to do before that.
Additionally, with #1829 (and #1979) the installation path (GISBASE) can be determined automatically from the path
to the grass.script.setup module (file), the executable (if it is called grass), or from a user-provided executable which
was be called (by the user) to obtain python_path.

The new setup method is now used in the notebooks.

This simplifoes usage documentaion in setup.py module. No GISBASE is needed. No explicit error checking
(errors are printed and/or raised automatically). sys.path now needs to be str/unicode.
Vaclav Petras 3 سال پیش
والد
کامیت
c810f67ab2

+ 3 - 3
doc/notebooks/basic_example.ipynb

@@ -35,9 +35,9 @@
     "from IPython.display import Image\n",
     "\n",
     "# Ask GRASS GIS where its Python packages are.\n",
-    "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n",
-    "os.environ[\"GISBASE\"] = gisbase\n",
-    "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n",
+    "sys.path.append(\n",
+    "    subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n",
+    ")\n",
     "\n",
     "# Import the GRASS GIS packages we need.\n",
     "import grass.script as gs\n",

+ 3 - 3
doc/notebooks/basic_example_grass_jupyter.ipynb

@@ -37,9 +37,9 @@
     "import sys\n",
     "\n",
     "# Ask GRASS GIS where its Python packages are.\n",
-    "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n",
-    "os.environ[\"GISBASE\"] = gisbase\n",
-    "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n",
+    "sys.path.append(\n",
+    "    subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n",
+    ")\n",
     "\n",
     "# Import the GRASS GIS packages we need.\n",
     "import grass.script as gs\n",

+ 4 - 4
doc/notebooks/grass_jupyter.ipynb

@@ -30,10 +30,10 @@
     "import subprocess\n",
     "import sys\n",
     "\n",
-    "# Add GRASS to path\n",
-    "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n",
-    "os.environ[\"GISBASE\"] = gisbase\n",
-    "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n",
+    "# Ask GRASS GIS where its Python packages are.\n",
+    "sys.path.append(\n",
+    "    subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n",
+    ")\n",
     "\n",
     "# Import GRASS packages\n",
     "import grass.script as gs\n",

+ 3 - 3
doc/notebooks/hydrology.ipynb

@@ -34,9 +34,9 @@
     "from collections import defaultdict\n",
     "\n",
     "# Ask GRASS GIS where its Python packages are.\n",
-    "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n",
-    "os.environ[\"GISBASE\"] = gisbase\n",
-    "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n",
+    "sys.path.append(\n",
+    "    subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n",
+    ")\n",
     "\n",
     "# Import the GRASS GIS packages we need.\n",
     "import grass.script as gs\n",

+ 3 - 3
doc/notebooks/solar_potential.ipynb

@@ -33,9 +33,9 @@
     "import sys\n",
     "\n",
     "# Ask GRASS GIS where its Python packages are.\n",
-    "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n",
-    "os.environ[\"GISBASE\"] = gisbase\n",
-    "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n",
+    "sys.path.append(\n",
+    "    subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n",
+    ")\n",
     "\n",
     "# Import the GRASS GIS packages we need.\n",
     "import grass.script as gs\n",

+ 3 - 3
doc/notebooks/viewshed_analysis.ipynb

@@ -35,9 +35,9 @@
     "import sys\n",
     "\n",
     "# Ask GRASS GIS where its Python packages are.\n",
-    "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n",
-    "os.environ[\"GISBASE\"] = gisbase\n",
-    "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n",
+    "sys.path.append(\n",
+    "    subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n",
+    ")\n",
     "\n",
     "# Import the GRASS GIS packages we need.\n",
     "import grass.script as gs\n",

+ 13 - 2
lib/init/grass.py

@@ -2133,9 +2133,18 @@ def io_is_interactive():
 
 
 def print_params(params):
-    """Write compile flags and other configuration to stderr"""
+    """Write compile flags and other configuration to stdout"""
     if not params:
-        params = ["arch", "build", "compiler", "path", "revision", "version", "date"]
+        params = [
+            "arch",
+            "build",
+            "compiler",
+            "path",
+            "python_path",
+            "revision",
+            "version",
+            "date",
+        ]
 
     # check if we are dealing with parameters which require dev files
     dev_params = ["arch", "compiler", "build", "date"]
@@ -2151,6 +2160,8 @@ def print_params(params):
     for arg in params:
         if arg == "path":
             sys.stdout.write("%s\n" % GISBASE)
+        elif arg in ["python_path", "python-path"]:
+            sys.stdout.write("%s\n" % gpath("etc", "python"))
         elif arg == "arch":
             val = grep("ARCH", linesplat)
             sys.stdout.write("%s\n" % val[0].split("=")[1].strip())

+ 5 - 20
python/grass/script/setup.py

@@ -36,34 +36,19 @@ Usage::
         # TODO: this have to be checked, maybe unix way is good enough
         grass8bin = '/Applications/GRASS/GRASS-8.0.app/'
 
-    # query GRASS GIS itself for its GISBASE
-    startcmd = [grass8bin, '--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
+    # query GRASS GIS itself for its Python package path
+    grass_cmd = [grass8bin, "--config", "python_path"]
+    process = subprocess.run(grass_cmd, check=True, text=True, stdout=subprocess.PIPE)
 
     # define GRASS-Python environment
-    grass_pydir = os.path.join(gisbase, "etc", "python")
-    sys.path.append(grass_pydir)
+    sys.path.append(process.stdout.strip())
 
     # import (some) GRASS Python bindings
     import grass.script as gs
     import grass.script.setup as gsetup
 
     # launch session
-    rcfile = gsetup.init(gisdb, location, mapset, grass_path=gisbase)
+    rcfile = gsetup.init(gisdb, location, mapset)
 
     # example calls
     gs.message('Current GRASS GIS 8 environment:')