简体   繁体   中英

python ordereddict or OrderedDict?

I'm so confused right now. I'm using PyYAML for editing some YAML files.

data = yaml.load_all(open('testingyaml.yaml'),Loader=yaml.RoundTripLoader)

My testingyaml.yaml file contains the following content:

spring:
  profiles: dev
  datasource:
    url: jdbc:postgresql://127.0.0.1:5432/nfvgrid
dns:
  enable: false
cassandra:
  host: 192.168.7.151

When I print data it prints the following:

ordereddict([('spring', ordereddict([('profiles', 'dev'), ('datasource', ordereddict([('url', 'jdbc:postgresql://127.0.0.1:5432/nfvgrid')]))])), ('dns', ordereddict([('enable', False)])), ('cassandra', ordereddict([('host', '192.168.7.151')]))])

I further want to perform some operations on this ordered dictionary but python throws an error NameError: name 'ordereddict' is not defined

It's usually OrderedDict but somehow PyYAML returns ordereddict. How should I solve this issue?

You are almost certainly not using pyyaml as stated, as it does not have a RoundTripLoader . Instead you are probably using ruamel.yaml .

This alternative uses its own ruamel.ordereddict on python 2 installations, and the native collections.OrderedDict on python 3. This alternative supports most operations that OrderedDict does so there is no reason you cannot manipulate it. See its documentation.

However, if you wish to convert from one to the other, you could do something like:

x = collections.OrderedDict(some_ruamel_ordered_dict.items())

There is something strange going on, or you are not using the code example to load that file and then get that print from data . If you are really using yaml.load_all that will give you back a generator object which allows you to step over the 1 or more YAML document in that file. Since you're not using document directive markers , it makes little sense to use load_all() :

from __future__ import print_function

import ruamel.yaml as yaml

datas = yaml.load_all(open('testingyaml.yaml'), Loader=yaml.RoundTripLoader)
print(datas, '\n', '-' * 50, sep='')
for data in datas:
    print(data['spring']['profiles'])
print(type(data))

gives: dev The actual type of data in the above example is a ruamel.yaml.comments.CommentedMap which is also what you would get if you did the simpler:

data = yaml.load(open('testingyaml.yaml'), Loader=yaml.RoundTripLoader)
print(type(data))

which prints <class 'ruamel.yaml.comments.CommentedMap'> (not the use of load() instead of loadall() .

The CommentedMap is derived from ordereddict

from ruamel.yaml.compat import ordereddict
from ruamel.yaml.comments import CommentedMap
assert issubclass(CommentedMap, ordereddict)

because for roundtripping (you are using the RoundTripLoader ) ruamel.yaml needs to preserve the order and have a place to attach any comments and other informations to preserve, which is not possible when using dict . ordereddict is a just a convenience class around ruamel.ordereddict (if available) or OrderedDict ¹.

You can of course import ordereddict yourself as above and use it, but if you don't need roundtripping nor preservation of order in your dictionaries (ie are fine with dict ) just use the standard loader:

data = yaml.load(open('testingyaml.yaml'))
print(type(data))

prints:

<type 'dict'>

I recommend not to "downgrade" by using PyYAML: it only implements the old 1.1 version of YAML, and although ruamel.yaml is a derivative of PyYAML, since it was derived, it has quite a few issues solved that originally wer filed against, and still pertain to, PyYAML ².


¹ ruamel.ordereddict is a (fast) C implementation of ordered dicts that existed already for a few years before OrderedDict appeared in the standard library, as the standard library version has a small subset of functionality, and until Python 3.5 was (slow) pure Python, switching to OrderedDict was never really an option for me.
² But then I am biased as I am the author of ruamel.yaml (and know that it needs more documentation).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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