¿Liberando bloqueos de archivos PyQGIS?

16

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

Estoy tratando de eliminar algunos orígenes de datos (usados temporalmente) llamando a QgsVectorFileWriter.deleteShapeFile , pero debo salir de QGIS antes de poder hacerlo. He cargado las fuentes en objetos QgsVectorLayer. ¿Deben recolectarse todos los objetos y las referencias a ellos antes de que pueda eliminar la fuente? ¿Hay alguna manera de forzar esto?

He logrado crear un ejemplo de código mínimo que falla. Asegúrese de que el directorio temporal esté vacío antes de ejecutar.

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 QgsVectorFileWriter para crear layer2 , en lugar del algoritmo de procesamiento. Me sale el mismo error si intento el algoritmo qgis:clip . Entonces, ¿es esto un error en el procesamiento? ¿Lo estoy usando mal?

    
pregunta Oystein 12.11.2013 - 16:09

1 respuesta

9

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

Resulta que funciona bien si agrega la capa al registro de mapas y luego la elimina de nuevo. El registro del mapa toma la propiedad de la capa, por lo que cuando se elimina del registro, los bloqueos se liberan. 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.

    
respondido por el Oystein 19.11.2013 - 10:01

Lea otras preguntas en las etiquetas