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

时间:2019-03-28 06:25:52

标签: hdf5 pytables external-links

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

例如:

假设file_name = "collection.h5",其中存储了外部链接

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

/ link1(ExternalLink)-> /files/data1.h5:/weights/Image
/ link2(ExternalLink)-> /files/data2.h5:/weights/Image

以此类推,

我知道,要取消对链接的引用,可以按照以下方式使用自然命名来完成此操作:

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

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

2 个答案:

答案 0 :(得分:0)

您可以使用iter_nodes()walk_nodes()walk_nodes是递归的,iter_nodes不是递归的。我对这个SO主题的回答说明了iter_nodes()的一个示例: cannot-retrieve-datasets-in-pytables-using-natural-naming 我发现您不能使用get_node()来引用ExternalLink。您需要使用不同的引用。

这是一个简单的示例,该示例从本地文件夹中的HDF5文件列表创建collection.h5,然后在iter_nodes()循环中使用for。请注意,这是一个非常基本的示例。它不会检查节点的对象类型(外部链接)。假定根级别的每个 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()

答案 1 :(得分:0)

当您在任何组级别具有一个ExternalLink时,这是一个更完整(鲁棒且复杂)的答案,可以处理一般情况。它与上面类似,但是使用walk_nodes(),因为它在根级别具有3个组,并包含一个针对ExternalLink类型的测试(请参见isinstance())。此外,它还显示了如何使用_v_children属性来获取节点字典。 (我无法让list_nodes()使用ExternalLink。)

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()