QGIS PyQGIS – Running PyQGIS Scripts Outside QGIS GUI Using GRASS Provider

pyqgispythonqgisqgis-3qgis-processing

I'm writing a script that I would like to work outside of QGIS GUI. The script uses the processing algorithm standalone just fine for the native algorithms, however I am experiencing errors when trying to run grass algorithms. The code I am currently using to initialise the environment come from the following post:
Using QGIS3 Processing algorithms from standalone PyQGIS scripts (outside of GUI)

import sys
from qgis.core import QgsProcessingRegistry
from qgis.analysis import QgsNativeAlgorithms
from qgis.core import (
     QgsApplication
)

QgsApplication.setPrefixPath('/usr', True)
qgs = QgsApplication([], False)
qgs.initQgis()

# Append the path where processing plugin can be found
sys.path.append('C:/OSGeo4W64/apps/qgis/python/plugins')

from processing.core.Processing import Processing
Processing.initialize()
QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())
import processing

This code works to initialise the environment and allows me to run QGIS native processing operations in standalone scripts. The issue arises when i try to run the following code:

# Grass Process
parameters = {
    '-f': False,
    'GRASS_RASTER_FORMAT_META': '',
    'GRASS_RASTER_FORMAT_OPT': '',
    'GRASS_REGION_CELLSIZE_PARAMETER': 0,
    'GRASS_REGION_PARAMETER': None,
    'areas': 'C:/TEMP/areas.tif',
    'direction': 'C:/TEMP/direction.tif',
    'format': 0,
    'input': 'C:/TEMP/DEM.tif',
    'output': 'C:/TEMP/DEM_Filled.tif'
}
processing.run('grass7:r.fill.dir',parameters)

The process runs successfully from within QGIS running from the python console, however when I run the script externally I get the following error from processing:

File "C:/OSGeo4W64/apps/qgis/python/plugins\processing\tools\general.py", line 96, in run
    return Processing.runAlgorithm(algOrName, parameters, onFinish, feedback, context)
File "C:/OSGeo4W64/apps/qgis/python/plugins\processing\core\Processing.py", line 181, in runAlgorithm
    raise QgsProcessingException(msg)
_core.QgsProcessingException: There were errors executing the algorithm.

I am running the scripts in the python environment initialised by: C:\OSGeo4W64\bin\python-qgis.bat

Best Answer

I've done some more digging in the QGIS code and have found a solution. In the definition for processing.run() I found the method to get the QgsProcessingAlgorithm object from the string name. This class has a method canExecute(). This method returns true for me with no error message and subsequently running the processing algorithm works:

alg = QgsApplication.processingRegistry().createAlgorithmById('grass7:r.fill.dir')
canExecute, errorMessage = alg.canExecute()
print(str(canExecute) + str(errorMessage))
processing.run('grass7:r.fill.dir', parameters)

I traced the canExecute() method through the QGIS code and found the same method within the processing definition for Grass7Algorithm.py. Here I discovered the solution could be simplified to the following two lines:

from processing.algs.grass7.Grass7Utils import Grass7Utils
Grass7Utils.checkGrassIsInstalled()

I hope someone else finds this useful.