简体   繁体   English

如何通过python在.yaml文件中存在的现有数据之间插入数据?

[英]how to insert data in between already existing data present in .yaml file through python?

I'm trying to create an logging software using Python and YAML. 我正在尝试使用Python和YAML创建日志记录软件。 I need to test multiple boards and I might need to take more than 1 trial per board. 我需要测试多个板,每个板可能需要进行1个以上的试用。 So I want to arrange the data in YAML file in ascending orders of board numbers to automate the analysis process. 因此,我想按板编号的升序排列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()

I've written this rather simple code just to make log entries. 我已经编写了这个相当简单的代码来创建日志条目。 I've looked for ways to insert the data in between 2 blocks but didn't find one. 我一直在寻找在2个块之间插入数据的方法,但没有找到一个。 My current output is (after manual entries): 我当前的输出是(手动输入后):

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

And output I want is: 我想要的输出是:

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

Can someone please guide me? 有人可以指导我吗? I'm totally new to YAML and Python. 我对YAML和Python完全陌生。

There are several problems with your code: 您的代码有几个问题:

  1. You open the file for appending, but you don't want to append, you want to insert. 您打开了要追加的文件,但是不想追加,而是要插入。 Of course that is possible, but then you need to know where to position the file pointer, read everything after that in a buffer, write your new stuff, then write the buffer. 当然可以,但是随后您需要知道文件指针的位置,在缓冲区中读取所有内容,然后编写新内容,然后编写缓冲区。 Knowing where to position your file pointer is going to be the difficult part. 了解文件指针的位置将是困难的部分。

  2. You do yaml.allow_duplicate_keys = True but that doesn't do anything in PyYAML. 您执行yaml.allow_duplicate_keys = True但是在PyYAML中不执行任何操作。 It is a ruamel.yaml feature, that allows you to read files with duplicate keys (disallowed by the YAML specification, but silently ignored by the non-conforming PyYAML library). 这是ruamel.yaml功能,它允许您使用重复的密钥读取文件(YAML规范不允许,但不合格的PyYAML库会静默忽略)。

  3. You should not manipulate the YAML file directly, and always use load the data from YAML, update it and dump. 您不应直接操作YAML文件,而应始终使用从YAML加载数据,对其进行更新和转储。 That way your YAML will be conforming, even if, for instance, one of your inputs contains a single or double quote, or spaces (as you can see from 'Trial ' , that needs quotes in YAML because of the space). 这样,即使您的输入之一包含单引号或双引号或空格(如您从'Trial '所见,由于空格而需要在YAML中加引号),您的YAML也会保持一致。

  4. You are only using mappings in your YAML file, but such lists of trials, lend themselves much better to sequences. 您只在YAML文件中使用映射,但是这样的试验列表更适合于序列。

  5. Your keys have enumeration information, this is almost always a bad idea, because you cannot know up-front what the key looks like. 您的密钥具有枚举信息,这几乎总是一个坏主意,因为您无法预先知道密钥的外观。 So instead of a key Board 1 you should have a key Board with a value 1 , or as value a mapping with numbers of the boards as key. 因此,而不是一个关键Board 1 ,你应该有一个键Board与值1 ,或值与板为重点的数字映射。 That way it is easy to get the data for a particular board number (or update the trials if handled in the same way) 这样,就很容易获取特定板号的数据(或以相同方式处理或更新试验)。


To start you should make the status.yaml file look like: 首先,您应该使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

or use: 或使用:

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

or (my favourite): 或(我的最爱):

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

In the first example you should walk over the Python list en insert a new trial, before the value of Board changes to be greater than your input board number. 在第一个示例中,您应该遍历Python列表,并在Board的值更改为大于输入的Board编号之前插入一个新的试用版。

To update the last example use ruamel.yaml (disclaimer I am the author of that package), so the keys in your mappings stay in the same order: 要更新最后一个示例,请使用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)

which updates status.yaml to become: 它将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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM