#python #list-comprehension #geospatial #python-xarray #rasterio
#python #понимание списка #геопространственный #python-xarray #rasterio
Вопрос:
Что произошло:
при попытке открыть 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
Комментарии:
1. Я подозреваю, что вы превышаете лимит открытых системных файлов — попробуйте ulimit, чтобы увидеть, решение состоит в том, чтобы закрыть файл после внесения изменений