考虑使用Jeff Knupp's blog中的with
语句的基本示例:
class File():
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
self.open_file = open(self.filename, self.mode)
return self.open_file
def __exit__(self, *args):
self.open_file.close()
我有testfile
,其中包含两行,' ABC'和' DEF'。一切都按预期工作:
with File('/tmp/testfile','r') as f:
txt = [x.strip() for x in f.readlines()]
print(txt)
# ['ABC', 'DEF']
在with
块之外调用类方法会给出预期的错误:
f.readlines()
ValueError Traceback(最近一次调用最后一次) in() ----> 1 f.readlines()
ValueError:关闭文件的I / O操作。
现在问我的问题:
如何使用gdal
对象而不是文件来实现相同的行为?
我有一个类方法,它应该从磁盘读取数据并将其放入gdal
栅格中进行进一步处理。完成后,我想适当地关闭生成的gdal
栅格。通常,这可以通过将其设置为None
并使用gdal.Unlink
来完成。
但是,当我将所有内容放入上一个示例中的上下文结构时,我仍然可以与with
块之外的数据集进行交互。
这是一个可重复的例子:
class Raster:
'''Raster class with sidelength s'''
def __init__(self,s):
self.sidelength = s
def __enter__(self):
# create raster in memory
driver = gdal.GetDriverByName('GTiff')
self.raster = driver.Create('/vsimem/inmem.tif', self.sidelength, self.sidelength, 1, gdal.GDT_Float32)
self.raster.GetRasterBand(1).WriteArray(np.random.rand(self.sidelength,self.sidelength))
return self.raster
def __exit__(self, *args):
# close file and unlink
self.raster = None
gdal.Unlink('/vsimem/inmem.tif')
with
块按预期工作:
with Raster(5) as r:
print(r)
# <osgeo.gdal.Dataset; proxy of <Swig Object of type 'GDALDatasetShadow *' at 0x7f8078862ae0> >
但是在阻止之后,对象仍然存在,我仍然可以读取值:
print(r)
#<osgeo.gdal.Dataset; proxy of <Swig Object of type 'GDALDatasetShadow *' at 0x7f8078044a20> >
print(r.ReadAsArray())
#[[0.2549882 0.80292517 0.23358545 0.6284887 0.7294142 ]
# [0.9310723 0.21535267 0.9054575 0.60967094 0.9937953 ]
# [0.69144976 0.01727938 0.16800325 0.61249655 0.1785022 ]
# [0.16179436 0.43245795 0.7042811 0.4809799 0.85534436]
# [0.67751276 0.7560658 0.9594516 0.6294476 0.3539126 ]]
答案 0 :(得分:3)
在保持对它的引用时,您无法真正关闭gdal数据集。您可以保留对Raster
实例的引用,并使用r.raster
访问with
块中的数据集。
class Raster:
'''Raster class with sidelength s'''
def __init__(self,s):
self.sidelength = s
def __enter__(self):
# create raster in memory
driver = gdal.GetDriverByName('GTiff')
self.raster = driver.Create('/vsimem/inmem.tif', self.sidelength, self.sidelength, 1, gdal.GDT_Float32)
self.raster.GetRasterBand(1).WriteArray(np.random.rand(self.sidelength,self.sidelength))
return self
def __exit__(self, *args):
# close file and unlink
self.raster = None
gdal.Unlink('/vsimem/inmem.tif')
with Raster(5) as r:
print(r.raster)
输出:
<osgeo.gdal.Dataset; proxy of <Swig Object of type 'GDALDatasetShadow *' at 0x04564728> >
在with
块之外,数据集无法访问:
r.raster is None
输出:
True
如果将另一个变量绑定到r.raster
,则会再次出现问题,因此您可能希望将其完全封装在Raster
实例中,以及您需要的任何功能。在这一点上,你或多或少会重新发明Rasterio,但如果你的需求很简单,可能比依赖它更好。
答案 1 :(得分:1)
正如评论中所建议的,Rasterio通过rasterio.open
实现了您正在寻找的行为。