7

What is the right way to import GRASS algorithms for a standalone Python script?

I tried the solutions (solution1, solution2), but they didn't help me.

Here's the code that doesn't import GRASS algorithms, but imports native QGIS 3.22.2 algorithms well:

import sys
import qgis.core
OSGeo_folder = r'C:\OSGeo4W'
sys.path.append(fr'{OSGeo_folder}\apps\qgis\python\plugins')
import processing
from grassprovider.Grass7AlgorithmProvider import Grass7AlgorithmProvider
from grassprovider.Grass7Utils import Grass7Utils

print(f'GRASS version={Grass7Utils.installedVersion(True)}')

processing.core.Processing.Processing.initialize()
qgis.core.QgsApplication.processingRegistry().addProvider(qgis.analysis.QgsNativeAlgorithms())
qgis.core.QgsApplication.processingRegistry().addProvider(Grass7AlgorithmProvider())

if __name__ == '__main__':
    processing.algorithmHelp('grass7:r.clump')
    print('=' * 40)
    processing.algorithmHelp("native:reclassifybytable")

The output is:

GRASS version=7.8.6
Algorithm "grass7:r.clump" not found.
========================================
Reclassify by table (native:reclassifybytable)

This algorithm reclassifies a raster band by assigning new class values based on the ranges specified in a fixed table. ...truncated...

MAYANK SHARMA
  • 474
  • 1
  • 4
  • 10
Comrade Che
  • 7,091
  • 27
  • 58
  • @BenW Thanks for your help. Trying to solve the problem, I installed the latest version of QGIS 3.22.2-Białowieża. Apparently, the problem is not in the bat file (I tried your bat file without success), but probably in the python code. Have you tried running the code from the question above? What was the result? – Comrade Che Jan 11 '22 at 09:27
  • Is this the same as the issue https://github.com/qgis/QGIS/issues/45935 reported in the QGIS GitHub repository? – Andrea Giudiceandrea Jan 11 '22 at 12:27
  • @AndreaGiudiceandrea Yes, it is exactly the same. But is is closed as fixed issue. – Comrade Che Jan 11 '22 at 12:33
  • The issue report https://github.com/qgis/QGIS/issues/45935 was reopened (see https://github.com/qgis/QGIS/issues/45935#issuecomment-1012085166 and https://github.com/qgis/QGIS/issues/45935#issuecomment-1013639912) and then hopefully fixed with the merging of the PR https://github.com/qgis/QGIS/pull/47114. – Andrea Giudiceandrea Feb 03 '22 at 13:26

2 Answers2

6

Here is how GRASS should be imported (because of a bug it does not work, see more here, thanks Andrea Giudiceandrea):

import sys
import qgis.core

OSGeo_folder = r'C:\OSGeo4W'
sys.path.append(fr'{OSGeo_folder}\apps\qgis\python\plugins')
import processing
from grassprovider.Grass7AlgorithmProvider import Grass7AlgorithmProvider

processing.core.Processing.Processing.initialize()
print(f'Number of registered algorithms = {len(qgis.core.QgsApplication.processingRegistry().algorithms())}')
qgis.core.QgsApplication.processingRegistry().addProvider(Grass7AlgorithmProvider())
print(f'Number of registered algorithms = {len(qgis.core.QgsApplication.processingRegistry().algorithms())}')
processing.algorithmHelp('grass7:r.clump')  # fail if "Algorithm "grass7:r.clump" not found."
Comrade Che
  • 7,091
  • 27
  • 58
  • The issue report https://github.com/qgis/QGIS/issues/45935 was reopened (see https://github.com/qgis/QGIS/issues/45935#issuecomment-1012085166 and https://github.com/qgis/QGIS/issues/45935#issuecomment-1013639912) and then hopefully fixed with the merging of the PR https://github.com/qgis/QGIS/pull/47114. – Andrea Giudiceandrea Feb 03 '22 at 13:26
5

I do not have 3.22 installed yet, so not tested in that version. I have tested this with 3.20.3 installed with the new OSGeo4W installer. If it doesn't work for you I will delete this answer.

Tested workflow is:

Save the following batch file (e.g. pyqgis_grass78.bat):

@echo off
SET OSGEO4W_ROOT=C:\OSGeo4W
call "%OSGEO4W_ROOT%"\bin\o4w_env.bat
call "%OSGEO4W_ROOT%\apps\grass\grass78\etc\env.bat"
@echo off
path %PATH%;%OSGEO4W_ROOT%\apps\qgis\bin
path %PATH%;C:\OSGeo4W\apps\Qt5\bin
path %PATH%;C:\OSGeo4W\apps\Python39\Scripts
set QGIS_PREFIX_PATH=%OSGEO4W_ROOT:\=/%/apps/qgis
set GDAL_FILENAME_IS_UTF8=YES
rem Set VSI cache to be used as buffer, see #6448
set VSI_CACHE=TRUE
set VSI_CACHE_SIZE=1000000
set PYTHONPATH=%PYTHONPATH%;%OSGEO4W_ROOT%\apps\qgis\python
set PYTHONHOME=%OSGEO4W_ROOT%\apps\Python39
set QT_PLUGIN_PATH=%OSGEO4W_ROOT%\apps\qgis\qtplugins;%OSGEO4W_ROOT%\apps\qt5\plugins

cmd.exe

Save the following script as a .py file (e.g. r_clump_test.py):

import sys

from qgis.core import QgsApplication

QgsApplication.setPrefixPath('C:/OSGeo4W/apps/qgis', True) qgs = QgsApplication([], False) qgs.initQgis()

sys.path.append('C:\OSGeo4W\apps\qgis\python\plugins')

import processing from processing.core.Processing import Processing Processing.initialize() processing.algorithmHelp('grass7:r.clump')

Place the .bat and .py files in the same directory, double click the batch file, then at the command prompt type: "python r_clump_test.py" (without the quotes) and hit enter.

The output (for me) was:

r.clump (grass7:r.clump)

Recategorizes data in a raster map by grouping cells that form physically discrete areas into unique categories.

---------------- Input parameters

input: Input layer

    Parameter type: QgsProcessingParameterRasterLayer

    Accepted data types:
            - str: layer ID
            - str: layer name
            - str: layer source
            - QgsProperty
            - QgsRasterLayer

title: Title for output raster map

    Parameter type: QgsProcessingParameterString

    Accepted data types:
            - str
            - QgsProperty

-d: Clump also diagonal cells

    Parameter type: QgsProcessingParameterBoolean

    Accepted data types:
            - bool
            - int
            - str
            - QgsProperty

output: Clumps

    Parameter type: QgsProcessingParameterRasterDestination

    Accepted data types:
            - str
            - QgsProperty
            - QgsProcessingOutputLayerDefinition

threshold: Threshold to identify similar cells

    Parameter type: QgsProcessingParameterNumber

    Accepted data types:
            - int
            - float
            - QgsProperty

GRASS_REGION_PARAMETER: GRASS GIS 7 region extent

    Parameter type: QgsProcessingParameterExtent

    Accepted data types:
            - str: as comma delimited list of x min, x max, y min, y max. E.g. '4,10,101,105'
            - str: layer ID. Extent of layer is used.
            - str: layer name. Extent of layer is used.
            - str: layer source. Extent of layer is used.
            - QgsMapLayer: Extent of layer is used
            - QgsProcessingFeatureSourceDefinition: Extent of source is used
            - QgsProperty
            - QgsRectangle
            - QgsReferencedRectangle
            - QgsGeometry: bounding box of geometry is used

GRASS_REGION_CELLSIZE_PARAMETER: GRASS GIS 7 region cellsize (leave 0 for default)

    Parameter type: QgsProcessingParameterNumber

    Accepted data types:
            - int
            - float
            - QgsProperty

GRASS_RASTER_FORMAT_OPT: Output Rasters format options (createopt)

    Parameter type: QgsProcessingParameterString

    Accepted data types:
            - str
            - QgsProperty

GRASS_RASTER_FORMAT_META: Output Rasters format metadata options (metaopt)

    Parameter type: QgsProcessingParameterString

    Accepted data types:
            - str
            - QgsProperty

---------------- Outputs

output: <QgsProcessingOutputRasterLayer> Clumps

Ben W
  • 21,426
  • 3
  • 15
  • 39
  • The output for me is as follows: "Algorithm "grass7:r.clump" is not found". Could you please update QGIS to version 3.22.2 and test again? I'm afraid that the programmers have changed something, because I haven't encountered this problem in older versions. – Comrade Che Jan 11 '22 at 09:58
  • @Comrade Che, sorry mate, I can't right now. My batch file is based on python-qgis.bat in C:\OSGeo4W\bin. You can check that file in your installation- maybe some paths have changed. Also check the path to the grass env.bat. Otherwise I'm not sure. – Ben W Jan 11 '22 at 10:30
  • In QGIS version 3.22, non-native providers (including GRASS) have been moved to plugins, which may affect the way it is imported. See the change log: https://www.qgis.org/en/site/forusers/visualchangelog322/index.html#feature-move-non-native-processing-providers-into-independent-plugins – Comrade Che Jan 11 '22 at 10:33
  • Yes, probably! I will delete this answer for now. – Ben W Jan 11 '22 at 11:06
  • Please don't delete your answer until we solve the problem. – Comrade Che Jan 11 '22 at 11:08
  • @Comrade Che, for a start, can you run grass r.clump from the toolbox and check history to see the Python syntax for the algorithm call? – Ben W Jan 11 '22 at 11:35
  • Here it is: processing.run("grass7:r.clump", { 'input':'C:/DELETE/GIS SE 13/data/raster.tif', 'title':'1', '-d':False, 'output':'C:/DELETE/GIS SE 13/data/1.tif', 'threshold':0, 'GRASS_REGION_PARAMETER':None, 'GRASS_REGION_CELLSIZE_PARAMETER':0, 'GRASS_RASTER_FORMAT_OPT':'', 'GRASS_RASTER_FORMAT_META':''}) – Comrade Che Jan 11 '22 at 11:56
  • Hmm, same as previous versions. It's getting late for me here but I will try to upgrade to 3.22 tomorrow and test. – Ben W Jan 11 '22 at 12:06
  • Ok. Seems we have found the bug - algorithm names are missing in the qgis.core.QgsApplication.processingRegistry().algorithms() after executing qgis.core.QgsApplication.processingRegistry().addProvider(Grass7AlgorithmProvider()) – Comrade Che Jan 11 '22 at 12:36