h5py:HDF5数据集名称与组名称冲突

问题描述 投票:0回答:3

注意:这是@hamo 的原始问题。
该问题已在这里更新/澄清为“答案”:https://stackoverflow.com/a/77574693/10462884
相关答案在这里:https://stackoverflow.com/a/77575182/10462884


这段代码让我工作了几个小时却没有找到解决方案。 该程序在文件中找不到路径,因此它创建了一个新的数据集。然而,它会抛出以下

TypeError()
:

TypeError: "Incompatible object (Dataset) already exists"

如果我尝试通过

dset = file[hdf5_path]
更新值,则会抛出此错误:

Unable to open object (message type not found)

这段代码产生了上面的问题:

    hdf5_path = "path/to/my/dataset"
    with h5py.File(hdf5_path, "r+") as file:
        if hdf5_path in file:
            dset = file[hdf5_path]
            dset[...] = new_data_set
        else:
            file.create_dataset(hdf5_path, data=pixel_count)

以下代码在循环中第二次生成错误,即创建组“my_path/to_another”:“无法创建组(未找到消息类型)”

    import h5py
    data_set = [1,2,3,4]
    fname = "temp.h5"
    h5_path = "my_path"
    with h5py.File(fname, "r+") as file:
        if h5_path in file:
            dset = file[h5_path] 
            dset[...] = data_set
        else:
            file.create_dataset(h5_path, data=data_set)

    h5_path = "my_path/to_another/dest"
    with h5py.File(fname, "r+") as file:
        current_path = ""
        for part in h5_path.split('/')[:-1]:
            current_path = f"{current_path}/{part}" if current_path else part
            if current_path not in file:
                file.create_group(current_path)
        if h5_path in file:
            dset = file[h5_path] 
            dset[...] = data_set
        else:
            file.create_dataset(h5_path, data=data_set)

会不会是文件损坏了?

python visual-studio-code hdf5 h5py python-3.11
3个回答
1
投票

这个答案是@hamo 的“所谓问题”答案的后续。正如您所发现的,您必须检查

file[dset_tag]
是否是数据集,而且还必须检查路径上的所有名称是否为组(用于数据集的最后一个名称除外)。逻辑变得有点棘手。我通过创建一个简单的函数来检查所有路径名是否不是数据集来解决这个问题。然后就可以在原来的逻辑中使用它了。我修改了您的示例以创建一个模拟您的问题的文件。该文件首先使用名为
post/cams/thermal
的数据集创建,然后尝试创建名为
post/cams/thermal/pixels
的数据集。

代码如下:

def group_path_ok(pset_path):
    pset_path = dset_tag.split('/')
    group_path = ''
    for name in pset_path[:-1]:
        group_path += '/' + name
        if group_path in file and isinstance(file[group_path], h5py.Dataset):
            print(f'group name: {group_path} in path is a dataset')
            return False
    return True
            
    
fname = "copyfile.h5"
pixel_count = [i for i in range(10)]
dset_tag = "post/cams/thermal"

with h5py.File(fname, "w") as file:
    file.create_dataset(dset_tag, data=pixel_count)

pixel_count = [i for i in range(17)]
dset_tag = "post/cams/thermal/pixels"   
with h5py.File(fname, "r+") as file:
    if group_path_ok(pset_path):
        if dset_tag in file:
            del file[dset_tag]
            print("Dataset deleted")
        file.create_dataset(dset_tag, data=pixel_count)

0
投票

两种方法都有错误,因此文件很可能没有损坏。我会解释,然后提供工作代码。

在第一个示例中,您使用

hdf5_path
作为 H5 文件名和数据集路径的名称。此外,
create_dataset()
方法引用
dset_tag
作为数据集名称。这些是拼写错误还是剪切粘贴错误?

在第二个示例中,第一个

with/as
块创建一个名为
my_path
的数据集。这会触发第二个
with/as
块中的错误。您正在尝试使用
h5_path = "my_path/to_another/dest"
创建数据集。这意味着
my_path
现在必须是 GROUP(当它刚刚创建为 DATASET 时)。这就是你收到错误的原因。此外,您不需要创建中间组;
create_dataset()
方法将为你做到这一点。我将您的索引修改为 h5py 首选格式(从
[...]
[()]
,并删除带有
dset = file[h5_path]
的行以减少代码)。

您的代码不会测试现有数据集中数据的修改。我添加了第三段来做到这一点。注意:只有当新数据与现有数据集的类型和形状匹配时,这才有效。如果形状发生变化,或者从整数更改为字符串,您将收到错误。更糟糕的是,如果新数据从整数更改为浮点数,您将收到未检测到的错误,因为浮点数将保存为整数。

修改后的代码如下:

import h5py  
data_set = [1,2,3,4]
fname = "temp.h5"
h5_path = "my_path/dest1"
with h5py.File(fname, "r+") as file:
    if h5_path in file:
        file[h5_path][...] = data_set
    else:
        file.create_dataset(h5_path, data=data_set)

h5_path = "my_path/dest2"
with h5py.File(fname, "r+") as file:
    if h5_path in file:
        file[h5_path][...] = data_set
    else:
        file.create_dataset(h5_path, data=data_set)

data_set = [11,12,13,14]
with h5py.File(fname, "r+") as file:
    if h5_path in file:
        file[h5_path][()] = data_set
    else:
        file.create_dataset(h5_path, data=data_set)
    print(file[h5_path][()])    

0
投票

好吧,我终于找到了所谓的问题:

import h5py

pixel_count = [i for i in range(17)]
fname = "copyfile.h5"
dset_tag = "post/cams/thermal/pixels"
with h5py.File(fname, "r+") as file:
    if dset_tag in file:
        del file[dset_tag]
        print("Dataset deleted")
    file.create_dataset(dset_tag, data=pixel_count)
    

这里的问题是热是原始文件中的一个数据集,而不是一个组!因此,“post/cams/ Thermal/pixels”不在文件中,因此不会被删除,但是我也无法创建数据集,因为它是组的子项。

错误信息,

“ValueError:无法创建数据集(名称已存在)”

并没有让我意识到问题是什么,直到这个答案让我走上了正轨。

© www.soinside.com 2019 - 2024. All rights reserved.