2

I need to load several vector layers for my QGIS project, so that I test every function of my script in every one of them. However, in the end I want to work only with one or two layers of interest and discard the others, so I would like to do that automatically.

I did that successfully with some layers, but there is one layer that is causing me problems and I haven't figured out why.

Here's some code:

Loading layers (these shouldn't be the problem almost for sure):

a2 = iface.addVectorLayer(path + ardida2, "", "ogr")
if not a2:
  print("Layer failed to load!")
  
a3 = iface.addVectorLayer(path + ardida3, "", "ogr")
if not a3:
  print("Layer failed to load!")

Now this is the function I've created to delete all of the loaded layers except the ones that I want to work with. The prints where only because I was trying to understand the problem.

def RemoveAllLayersExcept(*layers):
    layer_ids = []
    for l in layers:
        layer_ids.append(l.id())
    print('layer_ids', layer_ids)
    for lyr in QgsProject.instance().mapLayers():
        print(lyr)
        if lyr not in layer_ids:
            print('not')
            QgsProject.instance().removeMapLayer(lyr)
        else:
            pass

Then I created a new layer - the one that is causing me problems. I need to edit this layer in an iterative process later. I followed a step-by-step example in OpenSourceOptions tutorial titled PyQGIS: Create a Shapefile:

# OPENSOURCEOPTIONS TUTORIAL - PYQGIS: Create a Shapefile

# create fields
layerFields = QgsFields()
layerFields.append(QgsField('ID', QVariant.Int))
layerFields.append(QgsField('Value', QVariant.Double))
layerFields.append(QgsField('Name', QVariant.String))

# Now define the file path for the new shapefile
# Note: the CRS used here is NAD 1983 UTM Zone 11 N

fn = 'D:/Sara/Trabalho/QGIS/pnogas/fireball_points.shp'
writer = QgsVectorFileWriter(fn, 'UTF-8', layerFields, QgsWkbTypes.Point,QgsCoordinateReferenceSystem('EPSG:26912'), 'ESRI Shapefile')

# For each feature we need to set the geometry (in this case a point)
# set the attribute values, then add it to the vector layer. 
feat = QgsFeature() # create an empty QgsFeature()
feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(cx14, cy14)))   # create a point and use it to set the feature geometry
feat.setAttributes([1, 1.1, 'one']) # set the attribute values
writer.addFeature(feat) # add the feature to the layer

layer_fireball = iface.addVectorLayer(fn, '', 'ogr')
if not layer_fireball:
  print("Layer failed to load!")
del(writer)

Then I remove the layers don't interest me:

RemoveAllLayersExcept(layer, layer_fireball)

And this is it. When I run the program for the first time, nothing happens. Here's what I get:

layer_ids ['COS2018_ardida2018_3_clip_cbf56f4b_e668_4c2e_9259_7d22d5943097', 'fireball_points_f92b32e0_f8bf_42c1_95e6_b317ddf6ee84']
COS2018_ardida2018_2_clip_45b241c4_fb9b_4654_9916_5ff08514c559
not
COS2018_ardida2018_3_clip_cbf56f4b_e668_4c2e_9259_7d22d5943097
fireball_points_f92b32e0_f8bf_42c1_95e6_b317ddf6ee84

which is in accordance to what I was expecting. But in a second and n-th times, I get:

Layer failed to load!
Traceback (most recent call last):
  File "C:\PROGRA~1\QGIS3~1.10\apps\Python37\lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
  File "<string>", line 676, in <module>
  File "<string>", line 104, in RemoveAllLayersExcept
AttributeError: 'NoneType' object has no attribute 'id'

Can you detect where the problem is? Why this error? And why does it happen only from the 2nd run on?

Thanks!

martineau
  • 119,623
  • 25
  • 170
  • 301
  • I am not familiar with PyQGIS. However, the error indicates that an `l` value produced by the `for l in layers:` has the value `None`. This implies that one of the `*layers` arguments that got passed to `RemoveAllLayersExcept()` was that value. – martineau Oct 31 '20 at 16:57
  • @martineau That's right, but I don't understand why that happens. Not even the fact that only the first run returns no errors. – Sara Isabel Aleixo Perestrelo Nov 02 '20 at 08:01
  • The issue has to do with the arguments being passed in a _call_ to `RemoveAllLayersExcept()`. However how that occurs isn't shown in any of the code in your question, so It's very doubtful anyone will be able to help you. – martineau Nov 02 '20 at 14:14

1 Answers1

4

Change RemoveAllLayersExcept method like below:

def RemoveAllLayersExcept(*keep_layers):
    layers = QgsProject.instance().mapLayers().values()
    will_be_deleted = [l for l in layers if l not in keep_layers]

    for layer in will_be_deleted:
        QgsProject.instance().removeMapLayer(layer)
Kadir Şahbaz
  • 418
  • 7
  • 21