1

UPDATE 2 Again I updated the code according to this: https://docs.qgis.org/3.28/en/docs/pyqgis_developer_cookbook/vector.html#modifying-vector-layers-with-an-editing-buffer. But now I have a again the problem, that no field is deleted. My code:

            dlayer = QgsVectorLayer(filename, 'layer_name', 'ogr')
            fieldnames = [field.name() for field in dlayer.fields()]
            print(len(fieldnames))
            dlayer.startEditing()
            dlayer.deleteAttributes([1])
            dlayer.commitChanges()
            fieldnamesUpdated = [field.name() for field in dlayer.fields()]
            print(len(fieldnamesUpdated))


UPDATE I updated the code according to the suggestions, but I still get the assertion error. This is the error: File "C:\PROGRA~1\QGIS32~1.3\apps\qgis\python\qgis\core\additions\edit.py", line 38, in __enter__ assert self.layer.startEditing() AssertionError.

This is my code now, what am I still doing wrong?

def deleteFields(path):
    xml_list_paths = []
for file in os.listdir(path):
    # make sure to only get the files with certain type, e.g. '.shp'
    if 'xml' in file:
        filename = f'{path}\{file}'
        # print(filename)
        xml_list_paths.append(filename)

        dlayer = QgsVectorLayer(filename, 'layer_name', 'ogr')

        # Create a list of the fieldnames you want to delete:
        fieldnames_to_delete = [field.name() for field in dlayer.fields()]
        # Enter Edit mode
        with edit(dlayer):
            # Create empty list we will fill with the fieldindexes
            fields_to_delete = []
            # Iterate over the list of fieldnames and get the indexes
            for fieldname_to_delete in fieldnames_to_delete:
                # Get the field index by its name:
                fieldindex_to_delete = dlayer.fields().indexFromName(fieldname_to_delete)
                # You can also check if the field exists
                if fieldindex_to_delete == -1:
                    # If it does not exist, just skip it and go to the next one. This may prevent a crash or error :)
                    continue
                # Append the index to the list
                fields_to_delete.append(fieldindex_to_delete)
            # Delete the fields by their indexes, note that it has to be a list:
            dlayer.dataProvider().deleteAttributes(fields_to_delete)
        # Update the fields, so the changes are recognized:
        dlayer.updateFields()






I have multiple (~4000) xml-files, which I want to merge. As I stumpled about a length-problem of a certain field, when trying to merge, and I only need the geometry of the objects, I would like to first remove all the attributes (or 'fields') from the files.

I tried to create script which should delete a field (as an example) but it seems to do literally nothing:

def mergeXMLFiles(path):
for file in os.listdir(path):

    if 'xml' in file:
        filename = f'{path}\{file}'



        # create Qgis-Vector layer 
        dlayer = QgsVectorLayer(filename, 'layer_name', 'ogr')

        # Create list from all field names and count 
        listoffields = [field.name() for field in dlayer.fields()]
        print(len(listoffields))

        # Delete the field with index 1 as an Example
        # and update the fields
        dlayer.dataProvider().deleteAttributes([1])
        dlayer.updateFields()

        # Create again a list of all fields in the layer and print
        # the count of the field names
        updatedlistoffields = [field.name() for field in dlayer.fields()]
        print(len(updatedlistoffields))

The second list should have less fields than the first list, but it doesn't, so I guess the deletion , so the code

            dlayer.dataProvider().deleteAttributes([1])
            dlayer.updateFields()

doesnt delete the field with index 1. What am I doing wrong?

i.i.k.
  • 1,427
  • 5
  • 11
  • 1
    Your layer is not in edit mode – MrXsquared Dec 19 '23 at 19:43
  • 2
    @MrXsquared's comment is the correct answer. You can either apply layer.startEditing() + layer.commitChanges() or edit(layer). See this article for more details: https://anitagraser.com/pyqgis-101-introduction-to-qgis-python-programming-for-non-programmers/pyqgis101-creating-editing-a-new-vector-layer/. Moreover, I would like to close this question, because it is a duplicate of this one https://gis.stackexchange.com/questions/109078/deleting-column-field-in-pyqgis. – Taras Dec 19 '23 at 20:24
  • Before the code above I tried layer.startEditing() and it threw me an error, which, when I read about, needed refactoring the layer. So I searched for another solution. I will try it again and come back to give feedback – i.i.k. Dec 20 '23 at 09:13
  • @Taras I had a look at https://anitagraser.com/pyqgis-101-introduction-to-qgis-python-programming-for-non-programmers/pyqgis101-creating-editing-a-new-vector-layer/, but it doesn't say how to delete attrubutes, but how to add them – i.i.k. Dec 20 '23 at 09:29
  • 2
    Putting the layer in edit mode is not needed if working directly with dataProvider() methods (no edit buffer). In fact, it is not recommended to mix QgsVectorLayer and QgsVectorDataProvider editing methods. Firstly you should print(dlayer.dataProvider().capabilitiesString()) to see if "Delete Attributes" is printed. If not, then deleting attributes is not supported by the data provider. Otherwise add more info (e.g. a sample) of the structure of your .xml files – Ben W Dec 20 '23 at 10:06
  • 1
  • @Ben W Thanks for helping! The function deleteAttributes() is supported. In the meantime I updated my code in the question, but it still doesn't work.... And I just see, that you QgsVectorLayer and edit doesn't work together. – i.i.k. Dec 20 '23 at 10:22
  • 1
    Does this answer your question? Deleting column/field in PyQGIS – Kalak Dec 20 '23 at 10:49
  • Unfortunately no, I tried that code and have included it in my question (under UPDATE) – i.i.k. Dec 20 '23 at 10:52
  • Could you check if layer is valid? e.g. print(dlayer.isValid()) I guess, QGIS does not recognize your xml structure as a valid layer. – YoLecomte Dec 20 '23 at 12:00
  • When I print the dlayer.isValid() I get 'True' – i.i.k. Dec 20 '23 at 12:18
  • 1
    Please share your file. It will be hard to go further without that. – YoLecomte Dec 20 '23 at 13:11
  • Unfortunately I cannot share the file, as the data is sensitive. I'm trying at the moment another method as I have a bit of a time pressure. I will first convert the files to gpkg as with that format I have more options to work on them as I have more toolings for that format (e.g. geopandas, and I guess also pyqgis may work with that file format better ... I hope). – i.i.k. Dec 20 '23 at 13:22
  • Effectively, that's a solution to work on a copy of your data after converting to a format that is easier to handle. gpkg is a good candidate to work with pyqgis. – YoLecomte Dec 20 '23 at 13:58

0 Answers0