1
dict = {
    i: [{'cam_R_m2c': cam_R_m2c},
        {'cam_T_m2c': cam_T_m2c},
        {'obj_bb': [0, 0, 0, 0]},
        {'obj_id': 0}
        ]
}
# list = [{'cam_R_m2c':cam_R_m2c},{'cam_T_m2c':cam_T_m2c},{'obj_bb': [0,0,0,0]},{'obj_id': 0}]
with open('./Data_collection/gt.yml','a+') as f:
    yaml.dump(dict,f)

I get a yaml file like this

0:
- cam_R_m2c:
  - 0.999988853931427
  - -0.0014960498083382845
  - -0.004474445711821318
  - 0.0014844260876998305
  - 0.9999955296516418
  - -0.0025999906938523054
  - 0.004478315357118845
  - 0.0025933198630809784
  - 0.9999865889549255
- cam_T_m2c:
  - 0.014818123541772366
  - 9.016657713800669e-05
  - 0.00015443217125721276
- obj_bb:
  - 0
  - 0
  - 0
  - 0
- obj_id: 0

However I want to get this format:

0:
- cam_R_m2c: [0.09630630, 0.99404401, 0.05100790, 0.57332098, -0.01350810, -0.81922001, -0.81365103, 0.10814000, -0.57120699]
  cam_t_m2c: [-105.35775150, -117.52119142, 1014.87701320]
  obj_bb: [244, 150, 44, 58]
  obj_id: 1

What should I do?

SuperStormer
  • 4,997
  • 5
  • 25
  • 35
darrenxc
  • 13
  • 2
  • @Tsyvarev That cannot answer the OPs question as that would leave the last line as `- {obj_id: 1}` flow style and not as `obj_id: 1`. The requested output is not semantically equivalent to the output obtained (even adjusted for the `0` values being different. It is a different data structure altogether. – Anthon Jul 22 '23 at 05:28
  • @darrenc It is much better to present complete minimal programs here on SO. It makes it easier to see where things go wrong, when we can reproduce your problem without guessing. In this case it also points out which library you are using, as to some reviewers it is not clear that the output you are getting cannot be gotten by the PyYAML (used in the answer they incorrectly mark this one as a duplicate) – Anthon Jul 22 '23 at 05:37
  • @Anthon: "The requested output is not semantically equivalent to the output obtained" - Yes, so without edit from OP we could only **guess** what part of obtained output the OP wants to change. I wonder how sure you are when post the answer with your guessing and claim that other guesses are wrong. – Tsyvarev Jul 22 '23 at 08:26
  • sorry for the incomplete post, but the answer below actually solved my problems. – darrenxc Jul 22 '23 at 09:51
  • @darrenxc: If you know that your question post is incomplete, then why don't you fix it? It is never late to edit a question post to the better state. And on Stack Overflow we care of the quality of the posts: a Question/Answer pair should help not only the asker, but future visitors too. – Tsyvarev Jul 23 '23 at 20:39

1 Answers1

2

There are a few problems with your code:

  • It is unlikely you want to append yaml to a file, use wb to open a file or preferably pass in a pathlib.Path instance, more concise and it opens the file in the correct way
  • dict is a reserved word in Python, you shouldn't mask it by using it as variable name
  • The officially recommended extension for files containing YAML documents has been .yaml since at least September 2006. YML format looks completely different as it an XML format.

The Python list like output for sequences in YAML is called flow-style (the other format is block style, which is the default for output in ruamel.yaml)

Then there is the issue that the output that you get is not semantically equivalent to the output that you want, which you can check if you load that data. In the output that you get (and in your definition of the variable dict), the value for the key 0 is a sequence of four items, each item being a mapping with a single key (in Python terms a list of four elements, each element being a dict). In the output that you want the value for that key is a sequence with a single element, and that element is a mapping with four keys.

If the requested output format is correct the solution is simple, you have to change the data structure:

from pathlib import Path
import ruamel.yaml

i = 0
cam_R_m2c = [0.09630630, 0.99404401, 0.05100790, 0.57332098, -0.01350810, -0.81922001, -0.81365103, 0.10814000, -0.57120699]
cam_T_m2c = [-105.35775150, -117.52119142, 1014.87701320]

data = {
    i: [{'cam_R_m2c': cam_R_m2c,  # curly braces removed on this and the following lines
         'cam_T_m2c': cam_T_m2c,
         'obj_bb': [244, 150, 44, 50],
         'obj_id': 1},      # I recommend getting in the habit of also adding a comman after the last key/value pair or element
        ]
}

out_file = Path('gt.yaml')
    
yaml = ruamel.yaml.YAML()
yaml.default_flow_style = None  # this makes the leaf nodes flow style
yaml.width = 2048  # to prevent line wrapping
yaml.dump(data, out_file)
print(out_file.read_text(), end='')

which gives:

0:
- cam_R_m2c: [0.0963063, 0.99404401, 0.0510079, 0.57332098, -0.0135081, -0.81922001, -0.81365103, 0.10814, -0.57120699]
  cam_T_m2c: [-105.3577515, -117.52119142, 1014.8770132]
  obj_bb: [244, 150, 44, 50]
  obj_id: 1

If your input is correct and you actually want:

0:
- cam_R_m2c: [0.09630630, 0.99404401, 0.05100790, 0.57332098, -0.01350810, -0.81922001, -0.81365103, 0.10814000, -0.57120699]
- cam_t_m2c: [-105.35775150, -117.52119142, 1014.87701320]
- obj_bb: [244, 150, 44, 58]
- obj_id: 1

it doesn't suffice to set yaml.default_flow_style:

import sys

data = {
    i: [{'cam_R_m2c': cam_R_m2c},
        {'cam_T_m2c': cam_T_m2c},
        {'obj_bb': [244, 150, 44, 50]},
        {'obj_id': 1},
        ]
}

yaml = ruamel.yaml.YAML()
yaml.default_flow_style = None 
yaml.width = 2048
yaml.dump(data, sys.stdout)

which gives:

0:
- cam_R_m2c: [0.0963063, 0.99404401, 0.0510079, 0.57332098, -0.0135081, -0.81922001, -0.81365103, 0.10814, -0.57120699]
- cam_T_m2c: [-105.3577515, -117.52119142, 1014.8770132]
- obj_bb: [244, 150, 44, 50]
- {obj_id: 1}

because the mapping with key obj_id is now also a leaf node.

To change an individual dict to a block style mapping:

def BSD(d):
    ret_val = ruamel.yaml.comments.CommentedMap(d)
    ret_val.fa.set_block_style()
    return ret_val

data = {
    i: [{'cam_R_m2c': cam_R_m2c},
        {'cam_T_m2c': cam_T_m2c},
        {'obj_bb': [244, 150, 44, 50]},
        BSD({'obj_id': 1}),
        ]
}

yaml = ruamel.yaml.YAML()
yaml.default_flow_style = None 
yaml.width = 2048
yaml.dump(data, sys.stdout)

which gives:

0:
- cam_R_m2c: [0.0963063, 0.99404401, 0.0510079, 0.57332098, -0.0135081, -0.81922001, -0.81365103, 0.10814, -0.57120699]
- cam_T_m2c: [-105.3577515, -117.52119142, 1014.8770132]
- obj_bb: [244, 150, 44, 50]
- obj_id: 1

You can also leave the default block style and change the individual lists to dump as flow-style sequences:

def FSL(d):
    ret_val = ruamel.yaml.comments.CommentedSeq(d)
    ret_val.fa.set_flow_style()
    return ret_val

data = {
    i: [{'cam_R_m2c': FSL(cam_R_m2c)},
        {'cam_T_m2c': FSL(cam_T_m2c)},
        {'obj_bb': FSL([244, 150, 44, 50])},
        {'obj_id': 1},
        ]
}

yaml = ruamel.yaml.YAML()
yaml.width = 2048
yaml.dump(data, sys.stdout)

which the same result:

0:
- cam_R_m2c: [0.0963063, 0.99404401, 0.0510079, 0.57332098, -0.0135081, -0.81922001, -0.81365103, 0.10814, -0.57120699]
- cam_T_m2c: [-105.3577515, -117.52119142, 1014.8770132]
- obj_bb: [244, 150, 44, 50]
- obj_id: 1
Anthon
  • 69,918
  • 32
  • 186
  • 246
  • 1
    Excellent quality answer, thank you. – Mark Setchell Jul 22 '23 at 07:36
  • 1
    Great answer! thank you so much! – darrenxc Jul 22 '23 at 09:46
  • @darrenxc As you stated in your other comment, my answer seemed to resolve the problem. If so, please consider accepting the answer (by clicking the V to the left of the top of the answer). That is the standard way for others to see that the answer is useful, without having to read throught comments. – Anthon Jul 22 '23 at 13:26