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.