2

I'm creating a layer from some database table using this code:

conString = 'dbname=\'mydatabase\' host=mymachine port=1521 user=\'myuser\' password=\'mypassword\' key=\'myID\' srid=25832 type=Point table="(SELECT * FROM myTable t WHERE 1 = 1 AND SESSION_ID = 1722 AND t.GEOMETRIE.get_gtype() = 1 )" (GEOMETRIE)' layer = QgsVectorLayer(conString, 'layerName', 'ORACLE') 

This just selects all point features from myTable and puts them into the layer layerName.

Now I want to store that layer to an Esri shapefile:

outPath = 'D://eP.shp' writer_options = QgsVectorFileWriter.SaveVectorOptions() writer_options.driverName = 'ESRI Shapefile' writer_options.actionOnExistingFile = QgsVectorFileWriter.ActionOnExistingFile.CreateOrOverwriteFile layer = QgsVectorFileWriter.writeAsVectorFormatV3(layer, outPath, QgsProject.instance().transformContext(), options=writer_options) 

Finally we put the layer into a groupLayer and render it in the map:

# put the layer into a groupLayer root = QgsProject.instance().layerTreeRoot() groupLayer = root.findGroup(resultLayerName) if groupLayer is None: groupLayer = root.addGroup(resultLayerName) groupLayer.addLayer(layer) # we need to put the layer into the map as well, but not to the legend QgsProject.instance().addMapLayer(layer, False) 

That works fine, when I execute it once. However when doing that again with the exact same layerName and filepath for the file to be created, I get the following error when calling QgsVectorFileWriter.writeAsVectorFormatV3 (translated from German):

'Creation of datasource failed (OGR-Error: D://eP.shp is not a directory.) 

I already tried to delete the shapefile using QgsVectorFileWriter.deleteShapeFile before creating it again, which interestingly deleted only the .shx, .cpg and the .prj files, but not the .dbf and the .shp files.

When I delete the layer from the layer tree in the UI, I can execute the above code. So I tried to do this via some code also:

root = QgsProject.instance().layerTreeRoot() groupLayer = root.findGroup(resultLayerName) if groupLayer: for child in groupLayer.children(): if isinstance(child, QgsLayerTreeLayer): QgsProject.instance().removeMapLayer(child.layerId()) root.removeChildNode(groupLayer) groupLayer = root.addGroup(resultLayerName) QgsProject.instance().reloadAllLayers() 

This however didn't change anything, so I wonder what I should do now.

I'm working with QGIS 3.40 on Windows.

5
  • windows won't let you delete or modify a file that is open in a (another) program Commented May 15 at 10:54
  • @IanTurton well, this is why I deleted the layer also upfront to no avail. Anyway, isn't this what the CreateOrOverwriteFile-option should handle appropriately? Commented May 15 at 11:00
  • @IanTurton Also, wouldn't then the error-message be something like "cannot delete the file because it's used by another process"?. Commented May 15 at 11:06
  • Well I'd check the source code but I suspect that it still fails on windows but as a Linux user I can't check Commented May 15 at 11:11
  • 1
    @IanTurton hmmm, I tried to delete the layer before deleting the shapefile (see my last code). However even than I was not able to delete the file. Also in file-explorer I cannot delete it, so there seems indeed be a lock on the file from QGIS. Commented May 15 at 11:21

1 Answer 1

2

Turns out QgsVectorFileWriter.ActionOnExistingFile.CreateOrOverwriteFile doesn't work on Windows, when the file is opened in QGIS. So the .shp-file and the .dbf-file can't be deleted. Admitedly the error-message from QGIS is really not of any help here.

The final "solution" was to delete the features within the shapefile, as mentioned in this topic:

root = QgsProject.instance().layerTreeRoot() groupLayer = root.findGroup(resultLayerName) if groupLayer: for child in groupLayer.children(): if isinstance(child, QgsLayerTreeLayer): provider = child.layer().dataProvider() #deleting all features in the Vector layer provider.truncate() QgsProject.instance().removeMapLayer(child.layerId()) root.removeChildNode(groupLayer) 

As writeAsVectorFormatV3 will call deleteShapeFile , when the option CreateOrOverwriteFile is set, we won't need to call the latter ourselves, so I omitted that step here. The important thing here is just to call truncate on the dataprovider in order to empty the layer. This eventually releases the lock from the layer when we remove it from the map.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.