I have a .yaml file I want to update with a Python code. Let's say it looks something like that:
state: 'present'
I'd like to have a code that changes the state and saves the file. I'm trying with something like this and fail:
def set_state(state):
with open("file_to_edit.yaml", 'rw') as f:
doc = yaml.load(f)
doc['state'] = state
yaml.dump(f)
I am using the 'yaml' package for Python.
Before anything else: never use
yaml.load()
if you don't have to, as it is in principle unsafe to do so. For this kind of simple structure (without tags) you should useyaml.safe_load()
(and the correspondingsafe_dump()
that will complain if your data cannot be safe_loaded after dumping).yaml.dump()
has the following signature:Of this only the first one needs to be given, that should be your
doc
variable. If you don't specify a stream, thendump()
writes data structure to an in memory file-object (like StringIO) and after writing returns the value as string.So although you could do:
this is inefficient and shows little understanding of how
yaml.safe_dump()
works.If you want to open the file for reading and writing you have to make sure you both reset the index in the file and truncate its content. This is usually not worth the effort so it is safer to re-open the file for writing:
(of course you make the filename a variable when you want to make sure you overwrite the original, so you cannot mistype it).
If you don't specify
default_flow_style=False
, your output will look like:The output will not include the superfluous quotes around
present
in your input. You can specifydefault_style="'"
as well, but this will also put quotes aroundstate
.If losing the quotes is a problem and you really want the output to look like the input, you should be using
ruamel.yaml
(disclaimer I am the author of that package), which can preserve the quotes on individual strings, handles YAML 1.2 (instead of YAML 1.1) and also preserves comments in your file.The problem is that
yaml.dump
doesn't actually write to a file. Instead, it returns the modified YAML as a string unless you write it directly to the file.The following should work:
My guess is that you didn't indent properly, since your function in its current state seems not to do anything. Python does care about indentation.
Try this:
You can try the following (it creates a new file to store the result):