寻找可能更好的方法来使用 glom 获取嵌套数据?

Looking for the likely better way to get at nested data with glom?

我有一个来自系统的特别讨厌的统计对象,我需要从中检索数据(为简洁起见,显示了许多统计条目中的两个)。

 'https://localhost/mgmt/tm/sys/performance/all-stats/TMM%20Memory%20Used': {'nestedStats': {'entries': {'Average': {'description': '5'},
                                                                                                         'Current': {'description': '5'},
                                                                                                         'Max(since 2019_11_12T02:47:10Z)': {'description': '5'},
                                                                                                         'Memory Used': {'description': 'TMM '
                                                                                                                                        'Memory '
                                                                                                                                        'Used'}}}},
 'https://localhost/mgmt/tm/sys/performance/all-stats/Utilization': {'nestedStats': {'entries': {'Average': {'description': '9'},
                                                                                                 'Current': {'description': '10'},
                                                                                                 'Max(since 2019_11_12T02:47:10Z)': {'description': '53'},
                                                                                                 'System CPU Usage': {'description': 'Utilization'}}}}}

目前,我在嵌套堆栈中多次使用 .get 方法,但本周末我在 Talk Python 上听 glom module 的作者讲话,认为这可能更清晰我的解决方案。确实如此,正如这段代码所做的那样,我将所有数据都放在一个循环中,而没有疯狂的 get 方法层(我今晚正在处理的上图第一个示例)。外键是长URL,内键是avg/current/max/desc.

stats = b.tm.sys.performances.all_stats.load()
for k, v in stats.entries.items():
    print('\n')
    spec = f'entries.{k}.nestedStats.entries'
    v_stats = glom(stats, spec)
    for k, v, in v_stats.items():
        spec = f'{k}.description'
        stat_vals = glom(v_stats, spec)
        print(f'{k}: {stat_vals}')

结果是我需要的数据:

Average: 5
Current: 5
Max(since 2019_11_12T02:47:10Z): 5
Memory Used: TMM Memory Used

就是说,此时我无法真正控制数据,我只是打印出来。我不认为我只是在摸索 glom 的力量,并且很好奇是否有人可以指出一个有助于我理解的例子?最终目标是将所有这些数据扁平化为一个包含 4 个条目的字典列表。

首先,在尝试之前,请确保 glom 已更新到当前版本 19.11.0 或更高版本。

glom 的文档将您要求的称为 Data-Driven-Assignment,而不是 glom 的强度。

查看 glom 文档 here

要使其正常工作,您可能需要 lambdas and/or 常规 Python 代码。

以下是我的工作尝试,将您的示例行复制到变量 d.

from glom import glom, Call, T, Iter

d = { ... }  # put your example lines into this dictionary.

def get_desc(subdict):
    return {k: v.get('description', None) 
            for k,v in subdict[1]['nestedStats']['entries'].items()}

spec = (Call(list, args=(T.items(),) ), Iter().map(get_desc).all())

result = glom(d, spec)

print(result)

结果

[
{'Average': '5', 'Current': '5', 'Max(since 2019_11_12T02:47:10Z)': '5', 'Memory Used': 'TMM Memory Used'}, 
{'Average': '9', 'Current': '10', 'Max(since 2019_11_12T02:47:10Z)': '53', 'System CPU Usage': 'Utilization'}
]

更新

下面的版本得到相同的结果,但避免了对辅助函数的需要。

规范的作用:

  • 调用将外部字典转换为元组列表
  • Iter 遍历列表。对于每个项目:
    1. 取元组的第二个元素
    2. get nestedStats.entries(这是另一个字典)
    3. Call 把这个 dict 变成一个元组列表
    4. 将此列表转换为包含键和描述的字典列表
    5. 将字典列表合并为一个字典
  • 获取迭代的所有结果

我建议尝试此操作并删除部分规范以查看会发生什么...

from glom import glom, Call, T, Iter, merge

# d = { ... }  # put your example lines into this dictionary.

spec = (
    Call(list, args=(T.items(),)),
    Iter(
        (
            T[1],
            "nestedStats.entries",
            Call(list, args=(T.items(),)),
            [{T[0]: (T[1], "description")}],
            merge,
        )
    ).all(),
)

result = glom(d, spec)

print(result)