You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python修改YAML文件中所有'top'键的百分比值?

解决YAML中批量修改"top"百分比值的问题

需求与问题

我需要完成以下操作:

  • 加载YAML文件
  • 查找所有名为"top"的键
  • 提取其百分比格式的值,给数值加5后重新格式化
  • 保存修改后的文件

目前编写的代码能找到目标值并计算出新值,但无法通过lookup函数返回的路径修改原始的data变量,请求帮助。

现有代码

import sys
from pathlib import Path
import ruamel.yaml
import re

in_file = Path('overview.yaml')
out_file = Path('new_overview.yaml')

yaml = ruamel.yaml.YAML()
data = yaml.load(in_file)

#Found this in some other thread
def lookup(sk, d, path=[]):
   # lookup the values for key(s) sk return as list the tuple (path to the value, value)
   if isinstance(d, dict):
       for k, v in d.items():
           if k == sk:
               yield (path + [k], v)
           for res in lookup(sk, v, path + [k]):
               yield res
   elif isinstance(d, list):
       for item in d:
           for res in lookup(sk, item, path + [item]):
               yield res

#For each found result
for path, value in lookup("top", data):

    #Remove the percentage sign
    cleanvalue = re.sub('%','', value)

    #Convert to float and add 5
    addvalue = float(cleanvalue) + 5

    #Print old and new value
    print(cleanvalue, addvalue)


#with open('husoversigt_changed.yaml', 'wb') as f:
#  yaml.dump(data, f)

YAML数据示例

type: custom:mod-card
card:
  type: vertical-stack
  cards:
    - type: picture-elements
      elements:
        - type: state-icon
          entity: light.zigbee_bedroom_light
          tap_action:
            action: more-info
          style:
            top: 31%
            left: 74%
        - type: state-icon
          entity: binary_sensor.zigbee_mailbox_on_off
          tap_action:
            action: more-info
          style:
            top: 3%
            left: 42%
        - type: state-icon
          entity: group.alarm_sensors
          tap_action:
            action: more-info
          style:
            top: 20%
            left: 48%

解决方案

问题出在原lookup函数返回的路径中,列表元素被直接加入路径,无法用来定位列表的索引位置。修改lookup函数,让它在遍历列表时记录索引而非元素本身,这样就能通过路径逐层定位到要修改的节点。

修改后的完整代码

import sys
from pathlib import Path
import ruamel.yaml
import re

in_file = Path('overview.yaml')
out_file = Path('new_overview.yaml')

yaml = ruamel.yaml.YAML()
data = yaml.load(in_file)

def lookup(sk, d, path=[]):
    # 查找目标键,返回(路径, 值),路径中列表项用索引表示
    if isinstance(d, dict):
        for k, v in d.items():
            if k == sk:
                yield (path + [k], v)
            yield from lookup(sk, v, path + [k])
    elif isinstance(d, list):
        for idx, item in enumerate(d):
            yield from lookup(sk, item, path + [idx])

# 遍历所有找到的"top"键
for path, value in lookup("top", data):
    # 处理数值:移除百分号、加5、重新格式化
    clean_value = re.sub('%', '', value)
    new_num = float(clean_value) + 5
    new_value = f"{new_num}%"
    
    # 通过路径定位到父节点,修改"top"键的值
    parent = data
    # 遍历路径的前n-1个元素,逐层进入父节点
    for key in path[:-1]:
        parent = parent[key]
    # 修改目标键的值
    parent[path[-1]] = new_value
    print(f"修改 {value} -> {new_value}")

# 保存修改后的文件
with open(out_file, 'wb') as f:
    yaml.dump(data, f)

关键修改说明

  1. lookup函数优化:遍历列表时使用enumerate获取索引idx,将索引加入路径,而非列表元素本身,这样路径中的每个元素都可以作为访问数据的键/索引。
  2. 路径定位修改:遍历路径的前n-1个元素,逐层进入到目标键的父节点,最后直接修改父节点中的目标键值。
  3. 值的格式化:计算出新数值后,重新拼接成百分比格式的字符串,确保YAML数据格式正确。

内容的提问来源于stack exchange,提问作者danededane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 00:10:36