I have about 40 layers with attribute tables that have many NULL columns. I downloaded the plugin "Delete NULL Fields from Vector Data", which works. I'd like to automate it using the QGIS Python API. The script I tried returned the following:
Traceback (most recent call last): File
"C:\PROGRA~1\QGIS32~2.3\apps\Python39\lib\code.py", line 90, in
runcode
exec(code, self.locals) File "", line 1, in File "", line 17, in File
"C:\PROGRA~1/QGIS32~2.3/apps/qgis/./python/plugins\processing\tools\general.py",
line 108, in run
return Processing.runAlgorithm(algOrName, parameters, onFinish, feedback, context) File
"C:\PROGRA~1/QGIS32~2.3/apps/qgis/./python/plugins\processing\core\Processing.py",
line 169, in runAlgorithm
raise QgsProcessingException(msg)
_core.QgsProcessingException: Error: Algorithm qgis:Delete_Null_Fields not found
This is my script:
# specify output folder and new filename
output_folder = '/path/to/output/folder'
new_name = layer.name() + '_nonull'
# get a list of all layers in the project
layers = QgsProject.instance().mapLayers().values()
# loop through each layer and delete null fields
for layer in layers:
# run the plugin
alg_params = {
'INPUT': layer,
'FIELDS': None,
'OUTPUT': output_folder + '/' + new_name + '.shp'
}
nonull_layer = processing.run('qgis:Delete_Null_Fields', alg_params)['OUTPUT']
# add the new layer to the project
QgsProject.instance().addMapLayer(nonull_layer, False)
# save the new layer to a file
file_info = QFileInfo(layer.source())
output_path = file_info.path() + '/' + new_name + '.shp'
QgsVectorLayer.exportLayer(nonull_layer, output_path, 'ESRI Shapefile')
From what I understood, the API was unable to find the plugin from the name I gave. I got it from the dev's git page. I also tried initialising it first using the dev's script before my code starts:
def classFactory(iface): # pylint: disable=invalid-name
"""Load Delete_Null_Fields class from file Delete_Null_Fields.
:param iface: A QGIS interface instance.
:type iface: QgsInterface
"""
#
from .delete_null_fields import Delete_Null_Fields
return Delete_Null_Fields(iface)
But it didn't work. Importantly, I am very new to programming. What is wrong with the code and how could I achieve my batch processing?
Best Answer
It looks like you are trying to run a gui based Python plugin as a processing algorithm, which simply isn't going to work. To use a
processing.run()
call like this, you must pass the method an actual processing algorithm which has been added to the processing toolbox by a processing provider (either native or 3rd party).While it is technically possible to programmatically access the classes and methods of an installed Python plugin, for example the following will open the dialog of the plugin:
how useful this actually is depends very much on the structure of the plugin.
In this instance, to achieve what you want, I think it is easier to write our own script.
Fortunately, we can write a fairly quick and simple script containing a function which will create a copy of the input layer, delete any fields with all NULL values and save the output to a specified folder, leaving the original input layer unchanged. We can then iterate over all the project layers, skipping any non-vector layers, and call our function, passing the layer object, the output path and output format as arguments.
Paste the script below into a new editor in the Python console, edit the output path and click run.