Please note that all solutions explained here are related to vector layer used as the input and QGIS native algorithms. The answer doesn't explain the results of other providers' tools. (GRASS, GDAL, SAGA, ...). They may be different from native ones.
QGIS 3:
OPTION 1: run()
method with memory output:
result = processing.run("native:buffer",
{'INPUT':'D:/foo/bar.shp',
...
'OUTPUT':'TEMPORARY_OUTPUT'
})
# OUTPUT
#`result = {'OUTPUT': <qgis._core.QgsVectorLayer object at 0x00...>}`
Result is a dictionary. result['OUTPUT']
gives an instance of a layer (QgsVectorLayer
). No layer is added. Option 1 is one and only solution that returns a reference for QgsVectorLayer
in QGIS 3.
It can be used in the following way:
result_layer = processing.run("alg_name", {..., "OUTPUT":'TEMPORARY_OUTPUT'})["OUTPUT"]
result_layer
is now qgis._core.QgsVectorLayer
. Since it's a memory layer, it should be added to the project using addMapLayer()
method.
Other Processing Options
OPTION 2: run()
method with file output:
result = processing.run("native:buffer",
{'INPUT':'D:/foo/bar.shp',
...
'OUTPUT':'c:/foo/baz.shp'})
# OUTPUT
# `result = {'OUTPUT': 'c:/foo/baz.shp'}`
Result is a dictionary, value is a string. No layer is added.
OPTION 3: runAndLoadResults()
method with file output
result = processing.runAndLoadResults("native:buffer",
{'INPUT':'D:/foo/bar.shp',
...
'OUTPUT':'c:/foo/baz.shp'})
# OUTPUT
# `result = {'OUTPUT': 'c:/foo/baz.shp'}`
Result is a dictionary, value is a string. A layer is added.
OPTION 4: runAndLoadResults()
method with memory output
result = processing.runAndLoadResults("native:buffer",
{'INPUT':'D:/foo/bar.shp',
...
'OUTPUT':'TEMPORARY_OUTPUT'
})
# OUTPUT
# `result = {'OUTPUT': 'buffer_0ae....'}`
Result is a dictionary, value is a string. A layer is added.
QGIS 2:
OPTION 1: runandload()
method with file output
result = processing.runandload("qgis:fixeddistancebuffer",
"c:/foo/bar.shp", 10, 5, False,
"c:/foo/baz.shp")
# OUTPUT
# `result = <*****.FixedDistanceBuffer instance at 0x00...>`
Result is an instance of related algorithm class. A layer is added.
OPTION 2: runandload()
method with memory output
result = processing.runandload("qgis:fixeddistancebuffer",
"c:/foo/bar.shp", 10, 5, False,
"memory:mem_layer")
# OUTPUT
# `result = <*****.FixedDistanceBuffer instance at 0x00...>`
Result is an instance of related algorithm class. A layer is added.
OPTION 3: runalg()
method with file output
result = processing.runalg("qgis:fixeddistancebuffer",
"c:/foo/bar.shp", 10, 5, False,
"c:/foo/baz.shp")
# OUTPUT
# `result = {'OUTPUT': "c:/foo/baz.shp"}`
Result is a dictionary, value is a string. No layer is added.
OPTION 4: runalg()
method with memory output
result = processing.runalg("qgis:fixeddistancebuffer",
"c:/foo/bar.shp", 10, 5, False,
"memory:mem_layer")
# OUTPUT
# `result = {'OUTPUT': "memory:mem_layer"}`
Result is a dictionary, value is a string. No layer is added.
Neither runalg
nor runandload
returns a layer reference/instance for output in QGIS 2.
I used that way to change layer order while processing. As I know, normally you can't add layer to legend while processing in QGIS 3 unlike QGIS 2.
Try that. But it's risky according to this post.
# add this method to your algorithm class.
def flags(self):
return super().flags() | QgsProcessingAlgorithm.FlagNoThreading
and
# add last two lines (feedback and context parameters) to your 'run' method
viewshed = processing.run('grass7:r.viewshed', {
'input': raster,
'coordinates': coordStr,
'observer_elevation': 0,
'target_elevation': 0,
'max_distance': Visibility_Distance,
'refraction_coeff': 0.14286,
'memory': 500,
'-c':False,
'-r':False,
'-b':False,
'-e':False,
'output':os.path.join(Results, 'my_output.tif'),
'GRASS_REGION_PARAMETER': tr_extent,
'GRASS_REGION_CELLSIZE_PARAMETER':0,
'GRASS_RASTER_FORMAT_OPT':'',
'GRASS_RASTER_FORMAT_META':''
},
feedback=feedback, # without these two lines
context=context) # QGIS may crash
# And then, try to add layer to map.
view = QgsRasterLayer(viewshed['output'], 'my_output','gdal')
QgsProject.instance().addMapLayer(view)
Best Answer
It will be possible in 3.2 in standard algorithms through the use of
QgsProcessingLayerPostProcessorInterface
.For 3.0, you'll need to grab the project's layer tree from
context.project().layerTreeRoot()
and manipulate it directly. But be aware that this isn't safe to do in anything but the main thread, so in 3.0 where there's no concept of layer post-processors (which run in the main thread) you'll need to tag your whole algorithm as thread-unsafe, by returning theQgsProcessingAlgorithm.FlagNoThreading
flag in your algorithm'sflags()
implementation.