Zwolnienie blokady plików PyQGIS?

16

Zastanawiałem się, co powoduje zwolnienie blokady plików w pyQGIS?

Próbuję usunąć kilka źródeł danych (używanych tymczasowo), dzwoniąc QgsVectorFileWriter.deleteShapeFile, ale muszę wyjść z QGIS, zanim będę mógł to zrobić. Załadowałem źródła do obiektów QgsVectorLayer. Czy wszystkie te obiekty i odniesienia do nich muszą zostać wyrzucone, zanim będę mógł usunąć źródło? Czy istnieje sposób, aby to wymusić?


Udało mi się stworzyć minimalną próbkę kodu, która zawodzi. Upewnij się, że temp dir jest pusty przed uruchomieniem.

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

Okazało się, że działa, jeśli używam QgsVectorFileWriterdo tworzenia layer2zamiast algorytmu przetwarzania. Otrzymuję ten sam błąd, jeśli wypróbuję qgis:clipalgorytm. Czy to błąd w przetwarzaniu? Czy używam tego źle?

Oysteina
źródło

Odpowiedzi:

9

Przepraszam, że wciąż odpowiadam na własne pytania, ale myślę, że znalazłem rozwiązanie.

Jak się okazuje, działa dobrze, jeśli dodasz warstwę do rejestru map, a następnie usuniesz ją ponownie. Rejestr map przejmuje własność warstwy, więc po jej usunięciu z rejestru blokady zostają zwolnione. Pamiętaj, że musisz dodać warstwę do legendy ( .addMapLayer(layer, addToLegend = False) nie będzie działać).

Nadal nie jestem pewien, czy nazwać to rozwiązaniem, czy obejściem, ale działa.

# ...

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

Jeśli ktoś ma więcej informacji, chętnie dowiem się o tym więcej.

Oysteina
źródło
muszę usunąć dwie takie warstwy ... jestem w stanie usunąć jedną z powyższych metod .. wszystkie inne pliki oprócz .dbf i .shp drugiej są usuwane .. czy istnieje jakieś rozwiązanie, aby usunąć te dwa pliki także?
rao