I am attempting to convert some ArcGIS arcpy command-line scripts to PyQGIS and am running into a problem working with memory layers. The script takes several vector files as input and progresses through a series of transformations to generate a final output. The original script performs those transformations in memory, rather than on disk, to improve overall performance. I have attempted to do the same in QGIS but have been unable to pass an output memory layer to the next process in line as its input. The only thing that I have been able to get to work is to first save the output to file, then use that file's path as input. I have tried various things like passing the output layer's id, name or source, but nothing works.
I've created a small example in which I read in and merge 3 Shapefiles, then attempt to pass the output layer to the dissolve algorithm. The exception that gets thrown is shown at the end. Note that if I pass the layer source with a prefix of "memory://", no error is thrown, but no output is generated. I am submitting the code through the QGIS Python console (3.16.11-Hannover).
import qgis.core
import os
def main():
sourceFiles = [r'D:\Path\To\Some\Shapefiles\Source_File_1.shp',
r'D:\Path\To\Some\Shapefiles\Source_File_2.shp',
r'D:\Path\To\Some\Shapefiles\Source_File_3.shp']
tempDir = r'D:\TEMP"
# Merge Input Files
procParams = \
{
'LAYERS' : sourceFiles,
'CRS' : QgsCoordinateReferenceSystem('EPSG:3857'),
'OUTPUT' : 'TEMPORARY_OUTPUT'
}
result = processing.run("native:mergevectorlayers", procParams)
mergedLayers = result['OUTPUT']
mergedName = "Merge_3_Files"
mergedPath = os.path.join(tempDir, mergedName + ".shp")
msgText = "Save To Merged File To: %s" % (mergedPath)
print(msgText)
QgsVectorFileWriter.writeAsVectorFormat(
mergedLayers, mergedPath, 'utf-8', driverName='ESRI Shapefile')
# Dissolve Merged Files - Tried Using The Following INPUTs, Only "mergedPath" Works
dissolvedURI = mergedLayers.id()
##dissolvedURI = mergedLayers.name()
##dissolvedURI = mergedLayers.source()
##dissolvedURI = "memory://" + mergedLayers.source()
##dissolvedURI = mergedPath
procParams = \
{ 'INPUT' :QgsProcessingFeatureSourceDefinition(
dissolvedURI,
selectedFeaturesOnly=False,
featureLimit=-1,
flags=QgsProcessingFeatureSourceDefinition.FlagOverrideDefaultGeometryCheck,
geometryCheck=QgsFeatureRequest.GeometryNoCheck),
'FIELD' :[],
'OUTPUT':'TEMPORARY_OUTPUT'
}
result = processing.run("native:dissolve", procParams)
dissolvedLayer= result['OUTPUT']
dissolvedName = "Dissolve_3_Files"
dissolvedPath = os.path.join(tempDir, dissolveName + ".shp")
msgText = "Save To Dissolved File To: %s" % (dissolvedPath)
print(msgText)
QgsVectorFileWriter.writeAsVectorFormat(
dissolvedLayer, dissolvedPath, 'utf-8', driverName='ESRI Shapefile')
################################################################################
main()
##RESULT
##------
exec(open('C:/Temp/tmp_othe4_4.py'.encode('utf-8')).read())
Save To Merged File To: D:\TEMP\Merge_3_Files.shp
##Traceback (most recent call last):
File "C:\PROGRA~1\QGIS\apps\Python39\lib\code.py", line 90, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
File "<string>", line 53, in <module>
File "<string>", line 43, in main
File "C:\PROGRA~1/QGIS/apps/qgis-ltr/./python/plugins\processing\tools\general.py", line 108, in run
return Processing.runAlgorithm(algOrName, parameters, onFinish, feedback, context)
File "C:\PROGRA~1/QGIS/apps/qgis-ltr/./python/plugins\processing\core\Processing.py", line 168, in runAlgorithm
raise QgsProcessingException(msg)
##_core.QgsProcessingException: Unable to execute algorithm
##Could not load source layer for INPUT: Merged_724ac35a_0ace_41d5_ad52_f174adfa02cb not found
QgsProject.instance().addMapLayer(result_1['OUTPUT'], False)I'm assuming that I would have to repeat something similar for each new memory layer after every intermediate step. – VicTorn Nov 06 '21 at 12:03addMapLayerline to my small test script and was able to pass the memory layer to the downstream call using itsid(),name()orsource()and all 3 options worked. Looking to forward to ripping out all of the disk writes in my full script and replacing them with these memory exchanges. Many thanks! – VicTorn Nov 06 '21 at 18:09