【问题标题】:Problems reopening netcdf file written with xarray/dask重新打开用 xarray/dask 编写的 netcdf 文件时出现问题
【发布时间】:2018-08-20 12:12:08
【问题描述】:

我正在使用 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,我会收到一条错误消息,指出它无法打开文件('资源暂时不可用' )。所以它似乎仍然在某个地方开放。

运行代码的第二部分(从# 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

【问题讨论】:

  • 你能加你的ncdump -houtput_file吗?如果错误来自此示例的写入或读取部分,最好了解一下。
  • @jhamman 感谢您指出这一点。我编辑了我的问题并添加了请求的输出。

标签: python dask netcdf python-xarray


【解决方案1】:

请注意:documentation 表明 close() 仅在读取文件时适用。当写入文件时,to_netcdf() 应该为您处理关闭文件。我打算将此放在评论中,但没有足够的代表来制作 cmets。

【讨论】:

  • @m-neish 感谢您的注意。我不确定写入文件时是否有必要。如果to_netcdf() 应该负责关闭文件本身,那么方法可能有问题?
【解决方案2】:

似乎this is a bug 将被修复。 安装已经包含修复程序的branch 解决了我的问题。

【讨论】:

    猜你喜欢
    • 2021-11-21
    • 2018-08-25
    • 2018-03-10
    • 2020-11-05
    • 1970-01-01
    • 2020-10-28
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    相关资源
    最近更新 更多