首页 > 解决方案 > xarray.open_rasterio 不能在列表理解中打开超过 ~400 个文件

问题描述

发生了什么

当尝试使用 列表理解打开 14,000 个文件时xarray.open_rasterio,循环永远不会完成。目标是打开所有这些 GeoTiff 文件,将波段维度更改为日期维度,按日期堆叠,然后另存为 .single .nc。它可以在列表理解中打开少于 400 个文件没有问题。在两台不同的 Linux 机器上就是这种情况。

但是,当我提前创建列表并使用常规 for 循环打开每个文件并将结果附加到列表时,它会在大约一分钟内按预期完成所有 14000 个文件。为什么使用列表理解时会出现性能差异/可能的错误?一般来说,我对 python 列表理解性能有什么遗漏吗?

此外,我使用 linux 命令lsof很快确定在列表理解中,大约 446 个文件保持打开状态,而脚本从未完成。如果我继续检查,该值会在 446 左右波动lsof(它列出了由带有 的进程打开的文件lsof -p)。所以看起来有些文件没有在正常时间内关闭。

你期望发生的事情:我认为这需要大约一分钟,因为打开一个文件大约需要 41 毫秒。

最小完整可验证示例:数据文件夹 chirps-clipped 可在此处下载:https ://ucsb.box.com/s/erqz20bgojhvpw2xpdbbcs17e131xxe4

import xarray as xr
import rioxarray as rio
from pathlib import Path
from datetime import datetime
%matplotlib inline

all_scenes_f = Path('../rasters/chirps-clipped')

all_precip_paths = list(all_scenes_f.glob("*"))
# for some reason the fll value is not correct. this is the correct bad value to mask by
testf = all_precip_paths[0]
x = rio.open_rasterio(testf)
badvalue = np.unique(x.where(x != x._FillValue).sel(band=1))[0]

def chirps_path_date(path):
    _, _, year, month, day, _ = path.name.split(".")
    day = day.split("-")[0]
    return datetime(int(year), int(month), int(day))


def open_chirps(path):
    data_array = rio.open_rasterio(path) #chunks makes i lazyily executed
    data_array = data_array.sel(band=1).drop("band") # gets rid of old coordinate dimension since we need bands to have unique coord ids
    data_array["date"] = chirps_path_date(path) # makes a new coordinate
    return data_array.expand_dims({"date":1}) # makes this coordinate a dimension

### each data file is small and isn't tiled so it is not a good idea to use chunking
# https://github.com/pydata/xarray/issues/2314

import rasterio
with rasterio.open(testf) as src:
    print(src.profile)

%timeit rio.open_rasterio(testf)

### This is where the file opening bug happens
daily_chirps_arrs = [xr.open_rasterio(path) for path in all_precip_paths]

还有什么我们需要知道的吗?

环境

xr.show_versions() 的输出
INSTALLED VERSIONS
------------------
commit: None
python: 3.8.5 | packaged by conda-forge | (default, Sep 16 2020, 18:01:20) 
[GCC 7.5.0]
python-bits: 64
OS: Linux
OS-release: 5.4.0-53-generic
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8
LOCALE: en_US.UTF-8
libhdf5: None
libnetcdf: None

xarray: 0.16.1
pandas: 1.1.4
numpy: 1.19.1
scipy: 1.5.2
netCDF4: None
pydap: None
h5netcdf: None
h5py: None
Nio: None
zarr: None
cftime: None
nc_time_axis: None
PseudoNetCDF: None
rasterio: 1.1.6
cfgrib: None
iris: None
bottleneck: None
dask: 2.27.0
distributed: 2.30.1
matplotlib: 3.3.2
cartopy: None
seaborn: None
numbagg: None
pint: None
setuptools: 49.6.0.post20200917
pip: 20.2.3
conda: None
pytest: None
IPython: 7.18.1
sphinx: None

标签: pythonlist-comprehensiongeospatialpython-xarrayrasterio

解决方案


推荐阅读