setup.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. """Setup and initialization functions
  2. Function can be used in Python scripts to setup a GRASS environment
  3. without starting an actual GRASS session.
  4. Usage::
  5. import os
  6. import sys
  7. import subprocess
  8. # define GRASS Database
  9. # add your path to grassdata (GRASS GIS database) directory
  10. gisdb = os.path.join(os.path.expanduser("~"), "grassdata")
  11. # the following path is the default path on MS Windows
  12. # gisdb = os.path.join(os.path.expanduser("~"), "Documents/grassdata")
  13. # specify (existing) Location and Mapset
  14. location = "nc_spm_08"
  15. mapset = "user1"
  16. # path to the GRASS GIS launch script
  17. # we assume that the GRASS GIS start script is available and on PATH
  18. # query GRASS itself for its GISBASE
  19. # (with fixes for specific platforms)
  20. # needs to be edited by the user
  21. grass7bin = 'grass70'
  22. if sys.platform.startswith('win'):
  23. # MS Windows
  24. grass7bin = r'C:\OSGeo4W\bin\grass70.bat'
  25. # uncomment when using standalone WinGRASS installer
  26. # grass7bin = r'C:\Program Files (x86)\GRASS GIS 7.0.0\grass70.bat'
  27. # this can be avoided if GRASS executable is added to PATH
  28. elif sys.platform == 'darwin':
  29. # Mac OS X
  30. # TODO: this have to be checked, maybe unix way is good enough
  31. grass7bin = '/Applications/GRASS/GRASS-7.0.app/'
  32. # query GRASS GIS itself for its GISBASE
  33. startcmd = [grass7bin, '--config', 'path']
  34. try:
  35. p = subprocess.Popen(startcmd, shell=False,
  36. stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  37. out, err = p.communicate()
  38. except OSError as error:
  39. sys.exit("ERROR: Cannot find GRASS GIS start script"
  40. " {cmd}: {error}".format(cmd=startcmd[0], error=error))
  41. if p.returncode != 0:
  42. sys.exit("ERROR: Issues running GRASS GIS start script"
  43. " {cmd}: {error}"
  44. .format(cmd=' '.join(startcmd), error=err))
  45. gisbase = out.strip(os.linesep)
  46. # set GISBASE environment variable
  47. os.environ['GISBASE'] = gisbase
  48. # define GRASS-Python environment
  49. grass_pydir = os.path.join(gisbase, "etc", "python")
  50. sys.path.append(grass_pydir)
  51. # import (some) GRASS Python bindings
  52. import grass.script as gscript
  53. # launch session
  54. rcfile = gscript.setup.init(gisbase, gisdb, location, mapset)
  55. # example calls
  56. gscript.message('Current GRASS GIS 7 environment:')
  57. print gscript.gisenv()
  58. gscript.message('Available raster maps:')
  59. for rast in gscript.list_strings(type='raster'):
  60. print rast
  61. gscript.message('Available vector maps:')
  62. for vect in gscript.list_strings(type='vector'):
  63. print vect
  64. # delete the rcfile
  65. os.remove(rcfile)
  66. (C) 2010-2012 by the GRASS Development Team
  67. This program is free software under the GNU General Public
  68. License (>=v2). Read the file COPYING that comes with GRASS
  69. for details.
  70. @author Martin Landa <landa.martin gmail.com>
  71. @author Vaclav Petras <wenzeslaus gmail.com>
  72. """
  73. # TODO: this should share code from lib/init/grass.py
  74. # perhaps grass.py can import without much trouble once GISBASE
  75. # is known, this would allow moving things from there, here
  76. # then this could even do locking
  77. import os
  78. import sys
  79. import tempfile as tmpfile
  80. def write_gisrc(dbase, location, mapset):
  81. """Write the ``gisrc`` file and return its path."""
  82. gisrc = tmpfile.mktemp()
  83. with open(gisrc, 'w') as rc:
  84. rc.write("GISDBASE: %s\n" % dbase)
  85. rc.write("LOCATION_NAME: %s\n" % location)
  86. rc.write("MAPSET: %s\n" % mapset)
  87. return gisrc
  88. # TODO: there should be a function to do the clean up
  89. # (unset the GISRC and delete the file)
  90. def init(gisbase, dbase='', location='demolocation', mapset='PERMANENT'):
  91. """Initialize system variables to run GRASS modules
  92. This function is for running GRASS GIS without starting it
  93. explicitly. No GRASS modules shall be called before call of this
  94. function but any module or user script can be called afterwards
  95. as if it would be called in an actual GRASS session. GRASS Python
  96. libraries are usable as well in general but the ones using
  97. C libraries through ``ctypes`` are not (which is caused by
  98. library path not being updated for the current process
  99. which is a common operating system limitation).
  100. To create a (fake) GRASS session a ``gisrc`` file is created.
  101. Caller is resposible for deleting the ``gisrc`` file.
  102. Basic usage::
  103. # ... setup GISBASE and PYTHON path before import
  104. import grass.script as gscript
  105. gisrc = gscript.setup.init("/usr/bin/grass7",
  106. "/home/john/grassdata",
  107. "nc_spm_08", "user1")
  108. # ... use GRASS modules here
  109. # remove the session's gisrc file to end the session
  110. os.remove(gisrc)
  111. :param gisbase: path to GRASS installation
  112. :param dbase: path to GRASS database (default: '')
  113. :param location: location name (default: 'demolocation')
  114. :param mapset: mapset within given location (default: 'PERMANENT')
  115. :returns: path to ``gisrc`` file (to be deleted later)
  116. """
  117. # TODO: why we don't set GISBASE?
  118. mswin = sys.platform.startswith('win')
  119. # define PATH
  120. os.environ['PATH'] += os.pathsep + os.path.join(gisbase, 'bin')
  121. os.environ['PATH'] += os.pathsep + os.path.join(gisbase, 'scripts')
  122. if mswin: # added for winGRASS
  123. os.environ['PATH'] += os.pathsep + os.path.join(gisbase, 'extrabin')
  124. # add addons to the PATH
  125. # copied and simplified from lib/init/grass.py
  126. if mswin:
  127. config_dirname = "GRASS7"
  128. config_dir = os.path.join(os.getenv('APPDATA'), config_dirname)
  129. else:
  130. config_dirname = ".grass7"
  131. config_dir = os.path.join(os.getenv('HOME'), config_dirname)
  132. addon_base = os.path.join(config_dir, 'addons')
  133. os.environ['GRASS_ADDON_BASE'] = addon_base
  134. if not mswin:
  135. os.environ['PATH'] += os.pathsep + os.path.join(addon_base, 'scripts')
  136. # define LD_LIBRARY_PATH
  137. if '@LD_LIBRARY_PATH_VAR@' not in os.environ:
  138. os.environ['@LD_LIBRARY_PATH_VAR@'] = ''
  139. os.environ['@LD_LIBRARY_PATH_VAR@'] += os.pathsep + os.path.join(gisbase, 'lib')
  140. os.environ['GIS_LOCK'] = str(os.getpid())
  141. # Set GRASS_PYTHON and PYTHONPATH to find GRASS Python modules
  142. if not os.getenv('GRASS_PYTHON'):
  143. if sys.platform == 'win32':
  144. os.environ['GRASS_PYTHON'] = "python.exe"
  145. else:
  146. os.environ['GRASS_PYTHON'] = "python"
  147. path = os.getenv('PYTHONPATH')
  148. etcpy = os.path.join(gisbase, 'etc', 'python') + os.pathsep + os.path.join(gisbase, 'gui', 'wxpython')
  149. if path:
  150. path = etcpy + os.pathsep + path
  151. else:
  152. path = etcpy
  153. os.environ['PYTHONPATH'] = path
  154. # TODO: isn't this contra-productive? may fail soon since we cannot
  155. # write to the installation (applies also to defaults for Location
  156. # and mapset) I don't see what would be the use case here.
  157. if not dbase:
  158. dbase = gisbase
  159. os.environ['GISRC'] = write_gisrc(dbase, location, mapset)
  160. return os.environ['GISRC']