如何使用 pytables 取消引用外部链接列表?

How to de-reference a list of external links using pytables?

我使用 pytables 创建了从一个 hdf5 文件到另一个文件的外部 links。我的问题是如何在循环中取消引用它?

例如:

让我们假设 file_name = "collection.h5",存储外部 link 的地方

我在根节点下创建了外部 links,当我遍历根下的节点时,我得到以下输出:

/link1(外部链接)-> /files/data1.h5:/weights/Image
/link2(外部链接)-> /files/data2.h5:/weights/Image

等等,

我知道要取消对 link 的引用,可以这样做,使用以下方式的自然命名:

f = open_file('collection.h5',mode='r')
plink1 = f.root.link1()
plink2 = f.root.link2()

但我想在 for 循环中执行此操作,对此有任何帮助吗?

您可以使用iter_nodes()walk_nodes()walk_nodes 是递归的,iter_nodes 不是。 iter_nodes() 的示例在我对此 SO 主题的回答中进行了解释: 我发现您不能使用 get_node() 来引用外部链接。您需要以不同的方式引用。

这是一个简单的示例,它从本地文件夹中的 HDF5 文件列表创建 collection.h5,然后在 for 循环中使用 iter_nodes()。请注意,这是一个非常基本的示例。它不检查节点的对象类型(GroupLeafExternalLink)。它假定根级别的每个 Node 都是一个 ExternalLink,并从该节点创建一个文件对象。还有其他 PyTables 方法和属性可以检查这些情况。有关更强大(复杂)的方法,请参阅下面的详细答案。

import tables as tb
import glob

h5f = tb.open_file('collection.h5',mode='w')
link_cnt = 0 
for h5name in glob.glob('./SO*.h5'):
    link_cnt += 1
    h5f.create_external_link('/', 'link'+str(link_cnt), h5name+':/')
h5f.close()

h5f = tb.open_file('collection.h5',mode='r')
for link_node in h5f.iter_nodes('/') : 
    print("``%s`` is an external link to: ``%s``" % (link_node, link_node.target))
    plink = link_node(mode='r') # returns a FILE object

h5f.close()

这是一个更完整(稳健且复杂)的答案,用于处理在任何组级别都有 ExternalLink 时的一般情况。它与上面类似,但使用 walk_nodes() 因为它在根级别有 3 个组,并且包括对 ExternalLink 类型的测试(参见 isinstance())。此外,它还展示了如何使用 _v_children 属性来获取节点字典。 (我无法 list_nodes() 使用外部链接。)

import tables as tb
import glob

h5f = tb.open_file('collection.h5',mode='w')
link_cnt = 0
pre_list = ['SO_53', 'SO_54', 'SO_55']
for h5f_pre in pre_list :
    h5f_pre_grp = h5f.create_group('/', h5f_pre)
    for h5name in glob.glob('./'+h5f_pre+'*.h5'):
        link_cnt += 1
        h5f.create_external_link(h5f_pre_grp, 'link_'+'%02d'%(link_cnt), h5name+':/')
h5f.close()

h5f = tb.open_file('collection.h5',mode='r')
for link_node in h5f.walk_nodes('/') : 
    if isinstance(link_node, tb.link.ExternalLink) :
        print('\nFor Node %s:' % (link_node._v_pathname) )
        print("``%s`` is an external link to: ``%s``" % (link_node, link_node.target))
        plink = link_node(mode='r') # this returns a file object for the linked file
        linked_nodes = plink._v_children
        print (linked_nodes)

h5f.close()