I know there are a few questions about this on SO, but I couldn't find what I was looking for.
I'm using pyyaml to read (.load()
) a .yml
file, modify or add a key, and then write it (.dump()
) again. The problem is that I want to keep the file format post-dump, but it changes.
For example, I edit the key en.test.index.few
to say "Bye"
instead of "Hello"
Python:
with open(path, 'r', encoding = "utf-8") as yaml_file:
self.dict = pyyaml.load(yaml_file)
Then, afther changing the key:
with open(path, 'w', encoding = "utf-8") as yaml_file:
dump = pyyaml.dump(self.dict, default_flow_style = False, allow_unicode = True, encoding = None)
yaml_file.write( dump )
Yaml:
Before:
en:
test:
new: "Bye"
index:
few: "Hello"
anothertest: "Something"
After:
en:
anothertest: Something
test:
index:
few: Hello
new: Bye
Is there a way to keep the same format?, for example the qoutes and order. Am I using the wrong tool for this?
I know maybe the original file it's not entirely correct, but I have no control over it (it's a Ruby on Rails i18n file).
Thank you very much.
First
To represent dictionary data is used following code:
It is why ordering is changed
Second
Information about how scalar type was presented (with double quote or not) is lost when reading (this is principal approach of library)
Summary
You can create own class based on 'Dumper' and to overload method 'represent_mapping' for changing behaviour how dictionary will be presented
For saving information about double quotes for scalar you must also create own class based on 'Loader', but i am afraid that it will affect and other classes and will doing it difficult
Use
ruamel.yaml
instead.Library Fight! A Tale of Two Libraries
PyYAML is effectively dead and has been for several years. To compound matters, the official project home at http://pyyaml.org appears to have been taken down recently. This site hosted the PyYAML issue tracker, documentation, and downloads. As of this writing, all are gone. This is nothing short of calamitous. Welcome to just another day in open-source.
ruamel.yaml
is actively maintained. Unlike PyYAML,ruamel.yaml
supports:yaml.dump()
to dump a dictionary loaded by a prior call toyaml.load()
:ruamel.yaml
cleverly respects all input formatting. Everything. The whole stylistic enchilada. The entire literary shebang. All.Library Migration: The Trail of Code Tears
Since
ruamel.yaml
is a PyYAML fork and hence conforms to the PyYAML API, switching from PyYAML toruamel.yaml
in existing applications is typically as simple as replacing all instances of this:...with this:
That's it.
No other changes should be needed. The
yaml.load()
andyaml.dump()
functions should continue to behave as expected – with the added benefits of now supporting YAML 1.2 and actively receiving bug fixes.Roundtrip Preservation and What It Can Do for You
For backward compatibility with PyYaml, the
yaml.load()
andyaml.dump()
functions do not perform roundtrip preservation by default. To do so, explicitly pass:Loader=ruamel.yaml.RoundTripLoader
keyword parameter toyaml.load()
.Dumper=ruamel.yaml.RoundTripDumper
keyword parameter toyaml.dump()
.An example kindly "borrowed" from
ruamel.yaml
documentation:It is done. Comments, ordering, quoting, and whitespace will now be preserved intact.
tl;dr
Always use
ruamel.yaml
. Never use PyYAML.ruamel.yaml
lives. PyYAML is a fetid corpse rotting in the mouldering charnel ground of PyPi.Long live
ruamel.yaml
.In my case, I want
"
if value contains a{
or a}
, otherwise nothing. For example:To perform that, copy function
represent_str()
from file representer.py in module PyYaml and use another style if string contains{
or a}
:To use it in your code:
In this case, no diffences between keys and values and that's enough for me. If you want a different style for keys and values, perform the same thing with function
represent_mapping