3

I am currently working on a script that searches for a currently loaded layer in PyQGIS and does some calculations. Then it removes the layer and deletes the whole shapefile in its directory.

Replicable example:

source_layer = QgsProject.instance().mapLayersByName("input1")[0] #the pointlayer input1 is currently loaded in the QGIS Project
#make something..... e.g.
QgsProject.instance().removeMapLayer(source_layer)
source_layer = None #according to the web to delete dependencies
del source_layer    #according to the web to delete dependencies
QgsVectorFileWriter.deleteShapeFile("XXXX/input1.shp")

But it does not delete the .shp and .dbf in the shapefile folder. I think there must be a permission problem. But I can't figure out how to fix it. Does anyone have any idea?

13
  • 1
    Does it work if you leave off the ".shp"? Do you have any files opened in other applications? Commented Oct 30, 2023 at 22:30
  • 1
    Works fine for me with QGIS 3.33.0 on Linux. Commented Oct 31, 2023 at 9:11
  • 1
    is it possible that Windows thinks the file is still open when you try to delete it?
    – Ian Turton
    Commented Oct 31, 2023 at 11:40
  • 1
    Can't help with windows I'm afraid
    – Ian Turton
    Commented Oct 31, 2023 at 16:53
  • 1
    I can confirm the same issue on Windows. A workaround, if the user actually uses a saved project, would be to save the project, close it, delete the shapefile, open the project again. Not elegant, but should work. Commented Oct 31, 2023 at 17:38

1 Answer 1

7

Even if you keep in mind several things regarding your code:

And after improvements, your code might look as follows:

# imports
from os import listdir, remove
from os.path import isfile, realpath, join, split, basename, splitext
from qgis.core import QgsProject, QgsVectorFileWriter

# referring to the original Vector layer
source_layer = QgsProject.instance().mapLayersByName("points2")[0]

# getting the real path where the Vector layer is stored
path_to_shp = realpath(source_layer.source())

# removing the Vector layer from the registry by its ID
QgsProject.instance().removeMapLayer(source_layer.id())

# deleting source_layer variable
del source_layer

# deleting the shapefile
QgsVectorFileWriter.deleteShapeFile(path_to_shp) # False

# getting file location dir and the shapefile name
shp_dir, shp_file = split(path_to_shp)
# getting shapefile pure name and pure extension
shp_file_name, shp_file_extension = splitext(shp_file)

# obtaining all files associated with the shapefile in the working dir
files_to_delete = [join(shp_dir, file) for file in listdir(shp_dir) if
                   isfile(join(shp_dir, file)) and shp_file_name in basename(file)]
# removing all files associated with the shapefile
for file in files_to_delete:
    remove(file)

You may still encounter several issues:

  • shapefile dependencies with some extensions .shp, .qmd, and .dbf can remain in the folder

  • PermissionError can yield:

    Traceback (most recent call last):
       File "C:\OSGeo4W\apps\Python39\lib\code.py", line 90, in runcode
         exec(code, self.locals)
       File "<input>", line 1, in <module>
       File "<string>", line 26, in <module>
    PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'D:\\qgis_test\\points2.dbf'
    

However, there is a solution (a combination of QGIS- and OS-related things), that should erase everything associated with a shapefile. The trick is to delete all features in the Vector layer, afterwards, the metadata file .dbf can be also erased.

Let's assume there is a shapefile called 'points2' and stored under D:/test/, see the image below:

input

To delete everything associated with a shapefile, try the following code:

# imports
from os import listdir, remove
from os.path import isfile, realpath, join, split, basename, splitext
from qgis.core import QgsProject, QgsVectorFileWriter

# referring to the original Vector layer
source_layer = QgsProject.instance().mapLayersByName("points2")[0]

# accessing Vector layer provider
provider = source_layer.dataProvider()

# getting the real path where the Vector layer is stored
path_to_shp = realpath(provider.dataSourceUri())

# deleting all features in the Vector layer
provider.truncate()

# removing the Vector layer from the registry by its ID
QgsProject.instance().removeMapLayer(source_layer.id())
   
# deleting the shapefile
QgsVectorFileWriter.deleteShapeFile(path_to_shp) # True

# getting file location dir and the shapefile name
shp_dir, shp_file = split(path_to_shp)
# getting shapefile pure name and pure extension
shp_file_name, shp_file_extension = splitext(shp_file)

# obtaining all files associated with the shapefile in the folder
files_to_delete = [join(shp_dir, file) for file in listdir(shp_dir) if
                   isfile(join(shp_dir, file)) and shp_file_name in basename(file)]
# removing all files associated with the shapefile
for file in files_to_delete:
    remove(file)

After the dir must be empty:

result


References:

0

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.