【问题标题】:how to insert data in between already existing data present in .yaml file through python?如何通过python在.yaml文件中现有的数据之间插入数据?
【发布时间】:2018-04-19 15:46:35
【问题描述】:

我正在尝试使用 Python 和 YAML 创建一个日志记录软件。我需要测试多块电路板,并且每块电路板可能需要进行 1 次以上的试验。 所以我想将 YAML 文件中的数据按板号升序排列,以自动化分析过程。

#!/usr/bin/python3

import yaml
import io
board_no = (input('Enter the board number: '))
trial_no = (input('Enter the trial no: '))
reading1 = int(input('Reading1: '))
status = input('Pass/Fail: ')
yaml.allow_duplicate_keys = True
basic_info = { 'Board ' + board_no:{
        'Trial ' + trial_no:{
            'Reading1 '  :  reading1,
            'Status ': status
           }
        }
   }
fp = "../yaml_101/test_list.yaml"
outfile = open (fp,'a')
yaml.dump(basic_info, outfile, indent = 4, default_flow_style = False)
outfile.close()

我编写了这个相当简单的代码只是为了创建日志条目。 我一直在寻找在 2 个块之间插入数据的方法,但没有找到。 我当前的输出是(手动输入后):

Board 1:
    Trial 1:
        'Reading1 ': 450
        'Status ': Pass
Board 2:
    Trial 1:
        'Reading1 ': 758
        'Status ': Fail
Board 3:
    Trial 1:
        'Reading1 ': 450
        'Status ': Pass
Board 2:
    Trial 2:
        'Reading1 ': 450
        'Status ': Pass

我想要的输出是:

Board 1:
    Trial 1:
        'Reading1 ': 450
        'Status ': Pass
Board 2:
    Trial 1:
        'Reading1 ': 758
        'Status ': Fail
Board 2:
    Trial 2:
        'Reading1 ': 450
        'Status ': Pass
Board 3:
    Trial 1:
        'Reading1 ': 450
        'Status ': Pass

有人可以指导我吗? 我对 YAML 和 Python 完全陌生。

【问题讨论】:

  • yaml 使用 dict 容器来移动数据,因此它们不会按您想要的顺序保存。

标签: python yaml pyyaml


【解决方案1】:

你的代码有几个问题:

  1. 您打开文件进行追加,但您不想追加,您想插入。当然这是可能的,但是你需要知道文件指针的位置,然后读取缓冲区中的所有内容,写入新内容,然后写入缓冲区。知道文件指针的位置将是困难的部分。

  2. 你做了yaml.allow_duplicate_keys = True,但这在 PyYAML 中没有任何作用。这是一个ruamel.yaml 功能,允许您读取具有重复键的文件(YAML 规范不允许,但不符合标准的 PyYAML 库会默默忽略)。

  3. 您不应直接操作 YAML 文件,而应始终使用从 YAML 加载数据、更新数据和转储。这样,您的 YAML 将符合要求,例如,即使您的一个输入包含单引号或双引号或空格(正如您从 'Trial ' 中看到的那样,由于空格需要在 YAML 中使用引号)。

  4. 您仅在 YAML 文件中使用映射,但此类试验列表更适合序列。

  5. 您的密钥具有枚举信息,这几乎总是一个坏主意,因为您无法预先知道密钥的外观。因此,您应该有一个带有值1 的键Board,而不是一个键Board 1,或者作为值,一个以板数作为键的映射。这样就很容易获取特定板号的数据(或者如果以相同方式处理,则更新试验)


首先,您应该使 status.yaml 文件看起来像:

- Board: 1
  Trial: 1
  Reading1: 450
  Status: Pass
- Board: 2
  Trial: 1
  Reading1: 758
  Status: Fail
- Board: 3
  Trial: 1
  Reading1: 450
  Status: Pass

或使用:

Boards:
  - nr: 1
    Trials:
    - nr: 1
      Reading1: 450
      Status: Pass
  - nr: 2
    Trials:
    - nr: 1
      Reading1: 758
      Status: Fail
  - nr: 3
    Trials:
    - nr: 1
      Reading1: 450
      Status: Pass

或(我最喜欢的):

Boards:
  1:
    Trials:
      1:
        Reading: 450
        Status: Pass
  2:
    Trials:
      1:
        Reading: 758
        Status: Fail
  3:
    Trials:
      1:
         Reading: 450
         Status: Pass

在第一个示例中,您应该遍历 Python 列表并在 Board 的值更改为大于您输入的板编号之前插入一个新的 Trial。

要更新最后一个示例,请使用 ruamel.yaml(免责声明我是该软件包的作者),因此您的映射中的键保持相同的顺序:

from pathlib import Path
import ruamel.yaml

status_file = Path('status.yaml')
yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=2)
yaml.preserve_quotes = True

data = yaml.load(status_file)

board_no = 2
 # no need to input the trial_no, it should be the next number for this board
trials = data['Boards'][board_no]['Trials']
trial_no = sorted(trials.keys())[-1] + 1
reading1 = 450
status = 'Pass'

trials[trial_no] = dict(Reading1=reading1, Status=status)

yaml.dump(data, status_file)

status.yaml 更新为:

Boards:
  1:
    Trials:
      1:
        Reading1: 450
        Status: Pass
  2:
    Trials:
      1:
        Reading1: 758
        Status: Fail
      2:
        Reading1: 450
        Status: Pass
  3:
    Trials:
      1:
        Reading1: 450
        Status: Pass

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    相关资源
    最近更新 更多