Liberando bloqueios de arquivo PyQGIS?

16

Eu queria saber o que desencadeia o lançamento de bloqueios de arquivos no pyQGIS?

Estou tentando excluir algumas fontes de dados (usadas temporariamente) chamando QgsVectorFileWriter.deleteShapeFile, mas preciso sair do QGIS antes de poder fazer isso. Carreguei as fontes nos objetos QgsVectorLayer. Todos esses objetos e referências a eles devem ser coletados como lixo antes que eu possa excluir a fonte? Existe uma maneira de forçar isso?


Eu consegui criar um exemplo de código mínimo que falha. Verifique se o diretório temporário está vazio antes de executar.

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."

Descobri que funciona se eu usar QgsVectorFileWriterpara criar layer2, em vez do algoritmo de processamento. Eu recebo o mesmo erro se tentar o qgis:clipalgoritmo. Então, isso é um bug no processamento? Estou usando errado?

Oystein
fonte

Respostas:

9

Desculpe por continuar respondendo minhas próprias perguntas, mas acho que encontrei uma solução.

Como se vê, funciona bem se você adicionar a camada ao registro do mapa e removê-la novamente. O registro do mapa assume a propriedade da camada; portanto, quando é excluída do registro, os bloqueios são liberados. Observe que você precisa adicionar a camada à legenda ( .addMapLayer(layer, addToLegend = False) não funcionará).

Ainda não tenho certeza se deve chamar isso de solução ou solução alternativa, mas ele funciona.

# ...

# 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):    
    # ...

Se alguém tiver mais informações, ficarei feliz em saber mais sobre isso.

Oystein
fonte
Eu tenho que excluir duas dessas camadas ... Eu sou capaz de excluir um usando o método acima .. todos os outros arquivos, exceto .dbf e .shp do segundo estão sendo excluídos .. existe alguma solução para excluir esses dois arquivos também?
rao