Search code examples
pythondictionaryupdatingshelve

Updating A Shelved Dictionary written on a file


I have a shelved dictionary 'word_dictionary' in a file and I can access it in the main program. I need to make a user able to add an entry to the dictionary. But I'm unable to save the entry in the shelved dictionary and I get the error:

Traceback (most recent call last):
  File "/Users/Jess/Documents/Python/Coursework/Coursework.py", line 16, in <module>
    word_dictionary= dict(shelf['word_dictionary'])
TypeError: 'NoneType' object is not iterable

When the code loops back around - the code works on the first run.

This is the code which is meant to update the dictionary:

    shelf = shelve.open("word_list.dat")
    shelf[(new_txt_file)] = new_text_list
    shelf['word_dictionary'] = (shelf['word_dictionary']).update({(new_dictionary_name):(new_dictionary_name)})
    #not updating
    shelf.sync()
    shelf.close()

And this is the code which doesn't work after the update doesn't complete (I don't think this is part of the problem but I may be wrong)

shelf = shelve.open("word_list.dat")
shelf.sync()
word_dictionary= dict(shelf['word_dictionary'])

Thank you in advance for your help and patience! UPDATE This is the start of the code where I call word_dictionary which is imported:

while True:
 shelf = shelve.open("word_list.dat")
 print('{}'.format(shelf['word_dictionary']))
 word_dictionary= dict(shelf['word_dictionary'])
 print(word_dictionary)
 word_keys = list(word_dictionary.keys())
 shelf.close()

This is how the original dictionary I want to add to sits:

shelf['word_dictionary'] = {'Hope Words': 'hope_words', 'Merry Words': 'merry_words', 'Amazement Words': 'amazement_words'}

Solution

  • The problem is that you have to separate shelve database updates from objects loaded by the database into memory.

    shelf['word_dictionary'] = (shelf['word_dictionary']).update({(new_dictionary_name):(new_dictionary_name)})
    

    This code loaded the dict into memory, called its update method, assigned the result of the update method back to the shelf then deleted the updated in-memory dictionary. But dict.update returns None and you overwrote the dictionary completely. You put the dict in a variable, update, and then save the variable.

    words = shelf['word_dictionary']
    words.update({(new_dictionary_name):(new_dictionary_name)})
    shelf['word_dictionary'] = words
    

    UPDATE

    There was a question whether the new data is saved when the shelf is closed. Here is an example

    # Create a shelf with foo
    >>> import shelve
    >>> shelf = shelve.open('word_list.dat')
    >>> shelf['foo'] = {'bar':1}
    >>> shelf.close()
    
    # Open the shelf and its still there
    >>> shelf = shelve.open('word_list.dat')
    >>> shelf['foo']
    {'bar': 1}
    
    # Add baz
    >>> data = shelf['foo']
    >>> data['baz'] = 2
    >>> shelf['foo'] = data
    >>> shelf.close()
    
    # Its still there
    >>> shelf = shelve.open('word_list.dat')
    >>> shelf['foo']
    {'baz': 2, 'bar': 1}