3

I want to make a script which

  • processes some algorithms with multiple layers as inputs
  • outputs some results in QGIS project
  • then save the layers as zip files in a specified folder

I have not been successful yet but I have found some interesting informations with post processing methods by Ben W and Kadir Şahbaz : Adding output layers of QGIS processing scripts to group using PyQGIS / Table of content abnormally closing after using showAttributeTable (Processing plugin)

from zipfile import ZipFile
from qgis.core import QgsProcessing
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingMultiStepFeedback
from qgis.core import QgsProcessingParameterVectorLayer
from qgis.core import QgsProcessingParameterFeatureSink
from qgis.core import QgsProcessingParameterFolderDestination
from qgis.core import QgsProcessingUtils
import processing
class MyClass(QgsProcessingAlgorithm):
# reference to the output layer id 
dest_id = {}
def initAlgorithm(self, config=None):
 self.addParameter(QgsProcessingParameterVectorLayer('path', 'path', types=[QgsProcessing.TypeVectorLine], defaultValue=None))
 self.addParameter(QgsProcessingParameterVectorLayer('point', 'point', types=[QgsProcessing.TypeVectorPoint], defaultValue=None))
 self.addParameter(QgsProcessingParameterFeatureSink('joint', 'jointure', optional=True, type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, defaultValue=None))
 self.addParameter(QgsProcessingParameterFeatureSink('output', 'final output', type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, supportsAppend=True, defaultValue=None))
 self.addParameter(QgsProcessingParameterFolderDestination('save', 'Save to folder :', createByDefault=True, defaultValue=None))
 
def processAlgorithm(self, parameters, context, model_feedback):
 feedback = QgsProcessingMultiStepFeedback(15, model_feedback)
 results = {}
 outputs = {}
 # lot of algorithms process
 # example of one of my ouputs/results
 outputs['RefactorSite'] = processing.run('native:refactorfields', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
 results['final output'] = outputs['RefactorSite']['OUTPUT']
 
 # pass results to post processing
 self.dest_id['One_of_my_processing_outputs'] = QgsProcessingUtils.mapLayerFromString(results['One_of_my_processing_outputs'], context)
 return results

Then I want to pass processed layers to post process to zip all of them to the specified folder

def postProcessAlgorithm(self, context, feedback):
 
 filenames = QgsProcessingUtils.mapLayerFromString(self.dest_id, context)
 
 with zipfile.ZipFile("multiple_files.zip", mode="w") as archive:
 for filename in filenames:
 archive.write(filename)
 return {}

My code does not work and throws this error:

"TypeError: QgsProcessingUtils.mapLayerFromString(): argument 1 has unexpected type 'QgsVectorLayer' " or "unexpected type 'dict' "

Here is the documentation for QgsProcessingUtils.mapLayerFromString().

What is wrong with my code?

asked Mar 3, 2022 at 11:59
7
  • I am facing a type error : " TypeError: QgsProcessingUtils.mapLayerFromString(): argument 1 has unexpected type 'QgsVectorLayer' " or "unexpected type 'dict' " with multiples outputs If anyone can better understand how this method works, here is the documentation qgis.org/pyqgis/3.22/core/… Commented Mar 3, 2022 at 14:35
  • 1
    You probably need to save the layers to file(s) then zip the file(s). See gis.stackexchange.com/questions/354517/… Commented Mar 3, 2022 at 18:01
  • I have tried to re-use one of the output in processAlgorithm : self.final_layer['Layer_out'] = QgsProcessingUtils.mapLayerFromString(results['Layer_out'], context) with this variable on top : final_layer = {} then tried to pass to ppa : def postProcessAlgorithm(self, context, feedback): lyr = QgsProcessingUtils.mapLayerFromString(final_layer, context) but it still does an error "File "<string>", line 266, in postProcessAlgorithm NameError: name 'final_layer' is not defined" Commented Mar 10, 2022 at 14:03
  • @BERA : QGIS already provide a save files algorithm but then I may require the post processing for ziping the saved files Commented Mar 10, 2022 at 14:26
  • Maybe you can save them to disk (if that is needed, I dont know), zip, delete them using for example os.remove Commented Mar 10, 2022 at 14:35

1 Answer 1

1

I forgot to answer my question. I found a "decent" solution with ppa:

def postProcessAlgorithm(self, context, feedback):
 
 path = 'your path url here'
 
 for elem in self.final_layers:
 ctxt = QgsProject.instance().transformContext() 
 name = elem.name()
 url = path + name + '.geojson'
 options = QgsVectorFileWriter.SaveVectorOptions()
 options.layerName = name
 options.fileEncoding = elem.dataProvider().encoding()
 options.driverName = "geoJSON"
 QgsVectorFileWriter.writeAsVectorFormatV2(layer=elem, fileName=url, context=ctxt, options=options)
 
 # zip files
 zipname = path + 'archived ' + datetime.datetime.now().strftime('%d-%m-%Y %H-%M') + '.zip'
 directory = pathlib.Path(path)
 with zipfile.ZipFile(zipname, mode="w") as archive:
 for file_path in directory.iterdir():
 last_part = file_path.parts[-1]
 if last_part.endswith('.zip'):
 continue
 archive.write(file_path, arcname=file_path.name)
answered Sep 19, 2022 at 13:17

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.