Forum Archive

yaml.dump() appending to file rather than overwriting

Sparky01-

yaml.dump() appending to file rather than overwriting
how do i make set 'hi' to 1 and 'hello' to 1

import yaml

class myClass():
  def __init__(self):
    self.configFile = open('config.yml', 'r+')
    self.config = yaml.load(self.configFile)
    self.config['hi'] = 1
    self.config['hello'] = 1
    yaml.dump(
      self.config,
      self.configFile,
      default_flow_style=False
    ) 
    print(self.config)
    # returns {'hi': 1, 'hello': 1} 

myClass()

config file before:

hi: 0
hello: 0

after:

hi: 0
hello: 0
hi: 1
hello 1

what i want:

hi: 1
hello: 1
ccc

TL;DR:
1. If you open() a file then you should close() it or even better, use with open as which will autoclose the file.
2. Opening files in r+ mode is complicated.

c = {"hi": 0, "hello": 0}
d = {"hi": 1, "hello": 1}
# print(c | d)  # Pythonista's version of Python is too old
c.update(d)
print(c)

Sparky01-

the python dictionary is fine and printing what i want, printing the dict prints
{'hi': 1, 'hello': 1}
but when i dump it puts the yaml at the end of the file rather than overriding the file

bennr01

@Sparky01

I haven't tested it, but I think the problem is that you aren't using file offsets correctly. Basically, right now you are reading the file, then continue writing from the last position you have read.

The best solution would be to seperate reading and writing the files.

import yaml

class MyClass():
  def __init__(self):
    with open('config.yml', 'r') as fin:
        self.config = yaml.load(fin)
    self.config['hi'] = 1
    self.config['hello'] = 1
    with open('config.yml', 'w') as fout:
        yaml.dump(
          self.config,
          fout,
          default_flow_style=False
        ) 
    print(self.config)
    # returns {'hi': 1, 'hello': 1} 

MyClass()

Alternatively, call self.configFile.seek(0) after reading. This sets the read/write offset to the beginning of the file. Be warned that this only works if the new file content has at least the same length as the original file content, otherwise trailing bytes will remain!

halloleooo

In a situation like this I would never write to the same file I read from.:

  1. read from the config file.
  2. Write to a new file.
  3. Rename the old config file to something like ..._bak.yml.
  4. Rename the new file to the name of the old config file.

My 2cts.

cvp

@halloleooo between 2 and 3: remove the previous bak file

halloleooo

@cvp Only when you use os.rename. If you use pathlib's Path.rename I think it silently overwrites the old backup file.

cvp

@halloleooo Ho. Nice, I didn't know, never too old to learn