I need to run a processing algorithm that is coded/called in different file than main file. I've read some posts (1, 2, 3, 4, 5) but they give a solution that runs algorithm in main file. When I use those examples, algorithms work.
But I have three files for standalone QGIS application. The application has a window which includes a layer tree, a map canvas and a button (the following image). The button calls a method, defined in another file, which includes calling a processing algorithm. When I click the button, I get an error: For example: Error: Algorithm native:buffer not found.
I couldn't figure out how/where to add the next lines of code which is presented as a solution.
from qgis.analysis import QgsNativeAlgorithms
import processing
from processing.core.Processing import Processing
Processing.initialize()
QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())
Minimal files' structure:
Example Files:
main.py
import os
import sys
from qgis.core import *
from qgis.PyQt.QtWidgets import QApplication
from qgis.analysis import QgsNativeAlgorithms
import processing
from processing.core.Processing import Processing
from viewer import Viewer
QgsApplication.setPrefixPath(os.environ['QGIS_PREFIX_PATH'], True)
qgs = QgsApplication([], True)
qgs.initQgis()
Processing.initialize()
QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())
# The algorithm works here, but doesn't work in funcs_.py
# params = {...}
# buf = processing.run("native:buffer", params)
app = QApplication(sys.argv)
main_window = Viewer()
main_window.show()
sys.exit(app.exec_())
qgs.exitQgis()
viewer.py
from qgis.core import *
from qgis.gui import *
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *
import funcs_
class Viewer(QMainWindow):
def __init__(self):
QMainWindow.__init__(self, None)
self.initGUI()
def initGUI(self):
self.canvas = QgsMapCanvas()
self.layer = QgsVectorLayer("shapefile_path", 'Layer1', 'ogr')
QgsProject.instance().addMapLayers([self.layer])
self.layout = QHBoxLayout()
self.root = QgsProject.instance().layerTreeRoot()
self.bridge = QgsLayerTreeMapCanvasBridge(self.root, self.canvas)
self.model = QgsLayerTreeModel(self.root)
self.model.setFlag(QgsLayerTreeModel.AllowNodeChangeVisibility)
self.model.setFlag(QgsLayerTreeModel.ShowLegend)
self.layer_treeview = QgsLayerTreeView()
self.layer_treeview.setModel(self.model)
self.layer_tree_dock = QDockWidget("Layers")
self.layer_tree_dock.setObjectName("layers")
self.layer_tree_dock.setWidget(self.layer_treeview)
self.button = QPushButton("Create Buffer")
self.button.clicked.connect(self._create_buffer)
self.splitter = QSplitter()
self.splitter.addWidget(self.layer_tree_dock)
self.splitter.addWidget(self.canvas)
self.splitter.addWidget(self.button)
self.layout.addWidget(self.splitter)
self.contents = QWidget()
self.contents.setLayout(self.layout)
self.setCentralWidget(self.contents)
def _create_buffer(self):
lyr = funcs_.create_buffer(self.layer)
QgsProject.instance().addMapLayers([lyr])
func_.py
import processing
def create_buffer(lyr):
params = {'INPUT':lyr, 'DISTANCE':15, 'OUTPUT':'memory:'}
buf = processing.run("native:buffer", params)
return buf["OUTPUT"]


app(i.e.,app = QApplication(sys.argv)andsys.exit(app.exec_())). Instead, useqgs.exec_()right beforeqgs.exitQgis(). In that way everything works fine. – Germán Carrillo Jan 07 '20 at 14:01sys.path.append('/path/to/python/plugins/folder')may be required before importing processing. As stated in https://gis.stackexchange.com/questions/279874/using-qgis3-processing-algorithms-from-standalone-pyqgis-scripts-outside-of-gui/279937#279937 – Germán Carrillo Jan 07 '20 at 14:09