释放PyQGIS文件锁?


16

我想知道是什么触发了pyQGIS中文件锁定的释放?

我试图通过调用删除一些数据源(临时使用)QgsVectorFileWriter.deleteShapeFile,但是必须退出QGIS才能这样做。我已经将源代码加载到QgsVectorLayer对象中。在删除源之前,是否必须对所有这些对象及其引用进行垃圾回收?有没有办法强制执行此操作?


我设法创建了一个失败的最小代码示例。在运行之前,请确保temp目录为空。

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

我发现,如果我使用QgsVectorFileWritercreate layer2而不是处理算法,它将起作用。如果尝试该qgis:clip算法,则会收到相同的错误。那么这是处理中的错误吗?我使用错了吗?

Answers:


9

很抱歉继续回答我自己的问题,但我想我找到了解决方案。

事实证明,如果将图层添加到地图注册表中,然后再次将其删除,则效果很好。地图注册表拥有该图层的所有权,因此,从注册表中删除该图层时,将释放锁。请注意,您必须将图层添加到图例(.addMapLayer(layer, addToLegend = False)无效)。

仍然不确定是将其称为解决方案还是解决方法,但这确实可以完成。

# ...

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

如果有人有更多信息,我很乐意进一步了解。


我必须删除两个这样的层...我能够使用上述方法删除一个..除第二个文件的.dbf和.shp之外的所有其他文件都将被删除..是否有解决方案来删除这两个文件也一样
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.