Search code examples
pythonyamlpyyaml

Append to YAML list - how do I only 'append' the value?


I have been googling for about the last hour and haven't found a solution yet. I'm trying to generate a .yaml file which should have the following format:

"objects":
   -"dog"
   -"cat"
   -"rabbit"

The file is initially empty (only objects should be there) and the names should get appended. this is how it looks at first:

"objects":

trying to append to an empty list gives me the following error:

Traceback (most recent call last):
  File "C:\others\py_projects\learn\controller\addNewItemController.py", line 67, in onSave
    cur_yaml["objects"].append(self._model.myObjectName)
AttributeError: 'NoneType' object has no attribute 'append'

My code below:

objectNameDict = [self._model.myObjectName]
        with open('files/object.yaml', 'r') as yamlfile:
            cur_yaml = yaml.safe_load(yamlfile)
            cur_yaml = {} if cur_yaml is None else cur_yaml
            cur_yaml["objects"].append(objectNameDict)
            print(cur_yaml)

        with open('files/object.yaml', 'w') as yamlfile:
            yaml.safe_dump(cur_yaml, yamlfile, explicit_start=True, allow_unicode=True, encoding='utf-8')

figured out the list issue (thanks to lasrks), but the first try always fails because the list is empty.

what should I do?


Solution

  • The issue is that you're trying to append a list to another list. Forget YAML for a moment and think about Python. If I start with a list...

    >>> mylist = ['thing1']
    

    ...and then try to append a list to it, I end up with a nested list:

    >>> mylist.append(['another', 'list'])
    >>> mylist
    ['thing1', ['another', 'list']]
    

    That's exactly what you're seeing in your question. If you want to add the items in the poorly named objectNameDict to an existing list, you want the extend method:

    >>> mylist = ['thing1']
    >>> mylist.extend(['another', 'list'])
    >>> mylist
    ['thing1', 'another', 'list']
    

    When you read in your initial YAML file, in which the objects key exists but is empty:

    ---
    objects:
    

    You end up with a data structure that looks like this:

    >>> import yaml
    >>> with open('file.yml') as yamlfile:
    ...   cur_yaml = yaml.safe_load(yamlfile)
    ...
    >>> cur_yaml
    {'objects': None}
    >>>
    

    In order to turn that into a list, you'll want to do something like:

    >>> if cur_yaml['objects'] is None:
    ...   cur_yaml['objects'] = []