¿Liberar bloqueos de archivos PyQGIS?

16

Me preguntaba qué desencadena la liberación de bloqueos de archivos en pyQGIS.

Estoy tratando de eliminar algunas fuentes de datos (usadas temporalmente) llamando QgsVectorFileWriter.deleteShapeFile, pero tengo que salir de QGIS antes de poder hacerlo. He cargado las fuentes en objetos QgsVectorLayer. ¿Deben recogerse todos estos objetos y referencias a ellos antes de que pueda eliminar la fuente? ¿Hay alguna manera de forzar esto?


Me las arreglé para crear una muestra mínima de código que falla. Asegúrese de que el directorio temporal esté vacío antes de ejecutarlo.

from qgis.core import *
import processing, os, gc

project_temp_dir = "C:/Path/To/My/Dir/"      
layer1_path = project_temp_dir + "layer1.shp"
layer2_path = project_temp_dir + "layer2.shp"
input_layer = QgsMapLayerRegistry.instance().mapLayersByName('in_layer')[0]
if not input_layer.isValid(): raise Exception("Failed to grab input layer")

# Create layer 1
err = QgsVectorFileWriter.writeAsVectorFormat(input_layer, layer1_path, "utf-8", input_layer.crs())   
if err != QgsVectorFileWriter.NoError: raise Exception("Failed to write layer 1")

# Load layer 1
layer1 = QgsVectorLayer(layer1_path, "lyr1", "ogr")
if not layer1.isValid(): raise Exception("Failed to load layer 1")

# Use layer 1 to create layer 2, read-only makes no difference
# if not layer1.setReadOnly(): raise Exception("Could not set layer 1 to read-only")
processing.runalg("qgis:reprojectlayer", layer1, "EPSG:54030", layer2_path)

# Load layer 2
layer2 = QgsVectorLayer(layer2_path, "lyr2", "ogr")
if not layer2.isValid(): raise Exception("Failed to load layer 2")

del layer1
del layer2 
del input_layer
gc.collect()
print "Garbage: " + str(gc.garbage) # Empty

# Remove data sources for layers - FAILS!!
for f in os.listdir(project_temp_dir):          
    if f.endswith(".shp") and not os.path.isdir(project_temp_dir + f):              
        if not QgsVectorFileWriter.deleteShapeFile(project_temp_dir + f):
            # F*%&ing locks. 
            print "Failed to clear project temp directory."

Descubrí que funciona si uso QgsVectorFileWriterpara crear layer2, en lugar del algoritmo de procesamiento. Me sale el mismo error si pruebo el qgis:clipalgoritmo. Entonces, ¿es esto un error en el procesamiento? ¿Lo estoy usando mal?

Oystein
fuente

Respuestas:

9

Lamento seguir respondiendo mis propias preguntas, pero creo que encontré una solución.

Resulta que funciona bien si agrega la capa al registro del mapa y luego la elimina nuevamente. El registro del mapa toma posesión de la capa, por lo que cuando se elimina del registro, se liberan los bloqueos. Tenga en cuenta que debe agregar la capa a la leyenda ( .addMapLayer(layer, addToLegend = False) no funcionará).

Todavía no estoy seguro de si llamar a esto una solución o una solución alternativa, pero hace el trabajo.

# ...

# Replace the following code (note: should do error checking on map registry functions):

# Load layer 1
layer1 = QgsVectorLayer(layer1_path, "lyr1", "ogr")
if not layer1.isValid(): raise Exception("Failed to load layer 1")
QgsMapLayerRegistry.instance().addMapLayer(layer1) #!!!!

# Use layer 1 to create layer 2  
processing.runalg("qgis:reprojectlayer", layer1, "EPSG:54030", layer2_path)

# Load layer 2
layer2 = QgsVectorLayer(layer2_path, "lyr2", "ogr")
if not layer2.isValid(): raise Exception("Failed to load layer 2")
QgsMapLayerRegistry.instance().addMapLayer(layer2) #!!!!

# Remove layer references
QgsMapLayerRegistry.instance().removeMapLayer(layer1.id()) #!!!!
QgsMapLayerRegistry.instance().removeMapLayer(layer2.id()) #!!!!

# Remove data sources for layers
for f in os.listdir(project_temp_dir):          
    if f.endswith(".shp") and not os.path.isdir(project_temp_dir + f):    
    # ...

Si alguien tiene más información, me encantaría saber más sobre esto.

Oystein
fuente
tengo que eliminar dos de esas capas ... puedo eliminar una usando el método anterior ... todos los demás archivos excepto .dbf y .shp de la segunda se están eliminando ... ¿hay alguna solución para eliminar esos dos archivos? ¿también?
rao