重新打开用 xarray/dask 编写的 netcdf 文件时出现问题
Problems reopening netcdf file written with xarray/dask
我正在 运行使用 dask 进行模拟并将我的输出结果存储在 xarray 数据集中。然后我将数据保存到 netcdf 文件中。
之后,我想重新打开文件以进行进一步的数据处理。打开文件有效,但是当我实际访问数据时(例如调用 ds.compute()
),我收到一个似乎与读取文件有关的错误。我首先认为这与写入后未正确关闭文件有关,但手动关闭它无济于事。
奇怪的是,如果数据不是用 dask 生成的,我打开文件和使用它的数据没有任何问题。如果我只是在数据集中存储一个带有随机数的 numpy 数组,一切正常。
我整理了一个小例子,你可以看看:
import numpy as np
import xarray as xr
import pandas as pd
import dask.array as da
import dask
from dask.distributed import Client
from itertools import repeat
@dask.delayed
def run_sim(a, b, n_time):
result = np.array([np.random.randn(n_time)*a,np.random.randn(n_time)+b])
return result
client = Client()
# Parameters
n_sims = 5
n_time = 100
a_vals = np.random.randn(n_sims)
b_vals = np.random.randn(n_sims)
output_file = 'out.nc'
# if I use this as output, computing the data after reopening the file
produces an error
out = da.stack([da.from_delayed(run_sim(*args), (2,n_time,),np.float64) for args in zip(a_vals, b_vals, repeat(n_time))])
# If I use this as output, reopening the netcdf file is no problem
#out = np.random.randn(n_sims,2,n_time)
ds = xr.Dataset({'var1': (['realization', 'time'], out[:,0,:]),
'var2': (['realization', 'time'],out[:,1,:])},
coords={'realization': pd.RangeIndex(n_sims),
'time': pd.Index(np.arange(n_time)*.1)})
# Save to a netcdf file -> at this point, computations will be carried out
print('Saving data to netcdf file.')
ds.to_netcdf(output_file)
# close the netcdf file after writing
ds.close()
# Reopen the file
print('Reopen the file.')
with xr.open_dataset(output_file, chunks={'realization': 2}) as ds:
# Now acces the data
ds.compute()
我得到的错误是(我只是复制最后几行,在尝试执行 ds.compute()
时出现):
~/miniconda3/lib/python3.6/site-packages/xarray/backends/netCDF4_.py in _open_netcdf4_group()
229 import netCDF4 as nc4
230
--> 231 ds = nc4.Dataset(filename, mode=mode, **kwargs)
232
233 with close_on_error(ds):
netCDF4/_netCDF4.pyx in netCDF4._netCDF4.Dataset.__init__()
netCDF4/_netCDF4.pyx in netCDF4._netCDF4._ensure_nc_success()
OSError: [Errno -101] NetCDF: HDF error: b'/home/user/output/out.nc'
编辑:
如果 运行 代码只到关闭文件(ds.close()
是执行的最后一行)并且在输出文件上执行 ncdump -h
,我会收到一条错误消息说它无法打开文件 ('Resource temporarily unavailable')。所以它似乎仍然在某处开放。
运行 代码的第二部分(从 # Reopen the file
开始)导致上述错误。
但之后,输出文件上的 ncdump -h
成功,产生预期的输出:
netcdf out {
dimensions:
realization = 5 ;
time = 100 ;
variables:
double var1(realization, time) ;
var1:_FillValue = NaN ;
double var2(realization, time) ;
var2:_FillValue = NaN ;
int64 realization(realization) ;
double time(time) ;
time:_FillValue = NaN ;
}
如果我再重新运行代码的最后一部分,我就不会再收到错误了。
我根据这些结果得出的以下结论是否正确?
- 问题出现是因为文件写入后没有正常关闭。
- 第一次(不成功)尝试打开文件至少正确关闭了它。
如果是这样,我该怎么做才能避免这个问题?
编辑2:
仅当我启动 dask.distributed.Client() 时才会出现问题。我也开了一个issue on the xarray GitHub page.
请注意:documentation 表示 close()
仅适用于从文件中 读取 的情况。当写入 文件时,to_netcdf()
应该会为您关闭文件。我打算把它放在评论中,但没有足够的代表发表评论。
看来this is a bug哪个会被修复。
安装已包含修复程序的 branch 解决了我的问题。
我正在 运行使用 dask 进行模拟并将我的输出结果存储在 xarray 数据集中。然后我将数据保存到 netcdf 文件中。
之后,我想重新打开文件以进行进一步的数据处理。打开文件有效,但是当我实际访问数据时(例如调用 ds.compute()
),我收到一个似乎与读取文件有关的错误。我首先认为这与写入后未正确关闭文件有关,但手动关闭它无济于事。
奇怪的是,如果数据不是用 dask 生成的,我打开文件和使用它的数据没有任何问题。如果我只是在数据集中存储一个带有随机数的 numpy 数组,一切正常。
我整理了一个小例子,你可以看看:
import numpy as np
import xarray as xr
import pandas as pd
import dask.array as da
import dask
from dask.distributed import Client
from itertools import repeat
@dask.delayed
def run_sim(a, b, n_time):
result = np.array([np.random.randn(n_time)*a,np.random.randn(n_time)+b])
return result
client = Client()
# Parameters
n_sims = 5
n_time = 100
a_vals = np.random.randn(n_sims)
b_vals = np.random.randn(n_sims)
output_file = 'out.nc'
# if I use this as output, computing the data after reopening the file
produces an error
out = da.stack([da.from_delayed(run_sim(*args), (2,n_time,),np.float64) for args in zip(a_vals, b_vals, repeat(n_time))])
# If I use this as output, reopening the netcdf file is no problem
#out = np.random.randn(n_sims,2,n_time)
ds = xr.Dataset({'var1': (['realization', 'time'], out[:,0,:]),
'var2': (['realization', 'time'],out[:,1,:])},
coords={'realization': pd.RangeIndex(n_sims),
'time': pd.Index(np.arange(n_time)*.1)})
# Save to a netcdf file -> at this point, computations will be carried out
print('Saving data to netcdf file.')
ds.to_netcdf(output_file)
# close the netcdf file after writing
ds.close()
# Reopen the file
print('Reopen the file.')
with xr.open_dataset(output_file, chunks={'realization': 2}) as ds:
# Now acces the data
ds.compute()
我得到的错误是(我只是复制最后几行,在尝试执行 ds.compute()
时出现):
~/miniconda3/lib/python3.6/site-packages/xarray/backends/netCDF4_.py in _open_netcdf4_group()
229 import netCDF4 as nc4
230
--> 231 ds = nc4.Dataset(filename, mode=mode, **kwargs)
232
233 with close_on_error(ds):
netCDF4/_netCDF4.pyx in netCDF4._netCDF4.Dataset.__init__()
netCDF4/_netCDF4.pyx in netCDF4._netCDF4._ensure_nc_success()
OSError: [Errno -101] NetCDF: HDF error: b'/home/user/output/out.nc'
编辑:
如果 运行 代码只到关闭文件(ds.close()
是执行的最后一行)并且在输出文件上执行 ncdump -h
,我会收到一条错误消息说它无法打开文件 ('Resource temporarily unavailable')。所以它似乎仍然在某处开放。
运行 代码的第二部分(从 # Reopen the file
开始)导致上述错误。
但之后,输出文件上的 ncdump -h
成功,产生预期的输出:
netcdf out {
dimensions:
realization = 5 ;
time = 100 ;
variables:
double var1(realization, time) ;
var1:_FillValue = NaN ;
double var2(realization, time) ;
var2:_FillValue = NaN ;
int64 realization(realization) ;
double time(time) ;
time:_FillValue = NaN ;
}
如果我再重新运行代码的最后一部分,我就不会再收到错误了。
我根据这些结果得出的以下结论是否正确?
- 问题出现是因为文件写入后没有正常关闭。
- 第一次(不成功)尝试打开文件至少正确关闭了它。
如果是这样,我该怎么做才能避免这个问题?
编辑2: 仅当我启动 dask.distributed.Client() 时才会出现问题。我也开了一个issue on the xarray GitHub page.
请注意:documentation 表示 close()
仅适用于从文件中 读取 的情况。当写入 文件时,to_netcdf()
应该会为您关闭文件。我打算把它放在评论中,但没有足够的代表发表评论。
看来this is a bug哪个会被修复。 安装已包含修复程序的 branch 解决了我的问题。