Aaron Christensen wrote:
> Hello,
>
> I am trying to figure out how to populate a shelve file with a nested
> dictionary.
>
> These are my requirements:
>
> -Create shelve file called people.db
> -Append the shelve file with new people (person_1, person_2, etc.).
> -Use a for loop to iterate through 'attributes' so that I do not need to
> write out the lengthy code line by line to populate to the shelve file.
> -Need to reference shelve file data for future use
>
> Here is the key/value format that I would like to append to the shelve
> file.
>
> person_1 = { 'name': 'Bob', 'type': 'employee', 'attributes':
> [{'game': 'basketball', 'high score': '100', 'time': '3.34'},
> {'game': 'bridge', 'high score': '10', 'time': '30.34'},
> {'game': 'foosball', 'high score': '2', 'time': '24'}]
> '''
> 50+ other attributes
> '''
> }
>
> # Example: s['person_1]['attributes'][2]['time'] would call out '24'.
> # 's' is from 's = shelve.open('people')'
> I have a dictionary dictPeople.py file (created using pprint() that
> contains the information of person_1, etc. And I am extracting only a
> small percentage of the data that is needed.
>
> I have tried the following, but I get an invalid key error.
>
> import shelve, dictPeople
> s = shelve.open('people')
> person = 'person_1'
> s[person]['name'] = dictPeople.person_1['name']
> s[person]['type'] = dictPeople.person_1['type']
> # I need to use this for loop because there are 50+ attributes.
> for attribute in range(0, len(dictPeople['attributes'][attribute])):
> s[person]['attributes'][attribute]['game'] = \
> dictPeople['attributes'][attribute]['game']
> s[person]['attributes'][attribute]['high score'] = \
> dictPeople['attributes'][attribute]['high score']
> s[person]['attributes'][attribute]['time'] = \
> dictPeople['attributes'][attribute]['time']
> It turns out, I get the key error because I am not allowed to reference a
> key/value pair the same way that I can with a dictionary. However, the
> crazy thing is that I can call values in the db file using the same exact
> format when trying to write.
>
> For example: I can read data from the .db file using:
>
> x = s['person_1']['name']
> print(x)
> BUT! I cannot write to that .db file using that exact format or I get an
> invalid key error. Makes no sense!
>
> s['person_1']['name'] = 'Bob'
> # Returns invalid key entry. Makes no sense.
> Therefore, I tried to extract data and populate the db file using the
> following:
>
> s[person] = { 'name': dictPeople.person_1['name'],
> 'type': dictPeople.person_1['type'],
> for attribute in range(0, len(dictPeople['attributes'][attribute])):
> ['game': dictPeople['attributes'][attribute]['game'],
> 'high score': dictPeople['attributes'][attribute]['high score'],
> 'time': dictPeople['attributes'][attribute]['time']]
>
> }
> But, this obvously doesn't work because of the for loop. How can I do
> this?
>
> -I am trying to figure out how to extract data from the dictionary
> dictPeople.py file and store it in the people.db file.
> -I am trying to add new people to the people.db file as more people become
> available.
> -I need to use the for loop because of the 50+ attributes I need to add.
> -My future steps would be to modify some of the data values that I extract
> and used to populate the people.db file, but my first step is to, at
> least, extract, and then populate the people.db file.
>
> Any help or guidance is greatly appreciated. Thank you for your time and
> reading my question.
You don't need these loops. The problem is that when you read the dict from
the db
db = shelve.open(...)
person = db["person_1"]
person is a Python object completely independent of the shelve and the
shelve has no way to trace changes to that object:
$ python3
Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import shelve
>>> db = shelve.open("tmp.shelve")
>>> person_1 = { 'name': 'Bob', 'type': 'employee', 'attributes':
... [{'game': 'basketball', 'high score': '100', 'time': '3.34'},
... {'game': 'bridge', 'high score': '10', 'time': '30.34'},
... {'game': 'foosball', 'high score': '2', 'time': '24'}]
... }
>>> db["person_1"] = person_1
>>> db["person_1"]["age"] = 42
>>> db.close()
>>> db = shelve.open("tmp.shelve")
>>> db["person_1"]
{'name': 'Bob', 'type': 'employee', 'attributes': [{'time': '3.34', 'high
score': '100', 'game': 'basketball'}, {'time': '30.34', 'high score': '10',
'game': 'bridge'}, {'time': '24', 'high score': '2', 'game': 'foosball'}]}
When you look at the data you see that there is no "age" key. The straight-
forward fix is to always use an assignment
db[key] = new_value
when you want a change:
>>> person = db["person_1"]
>>> person["age"] = 42
>>> db["person_1"] = person
>>> db.close()
That way the change will survive:
>>> db = shelve.open("tmp.shelve")
>>> db["person_1"]["age"]
42
Alternatively you can open the shelve with writeback=True:
>>> db = shelve.open("tmp.shelve", writeback=True)
>>> db["person_1"]["height"] = 2.0
>>> db.close()
>>> db = shelve.open("tmp.shelve", writeback=True)
>>> db["person_1"]["height"]
2.0
That way every value will be written back (even when you don't modify it)
and therefore all mutations persist, but you pay for the convenience with
superfluous caching and writing.
--
https://mail.python.org/mailman/listinfo/python-list