Path: csiph.com!fu-berlin.de!uni-berlin.de!not-for-mail From: Peter Otten <__peter__@web.de> Newsgroups: comp.lang.python Subject: Re: In Python 3, how to append a nested dictionary to a shelve file with the added difficulty of using a for loop? Date: Tue, 22 Dec 2015 01:23:51 +0100 Organization: None Lines: 148 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7Bit X-Trace: news.uni-berlin.de IbfU/B2WMyRR/f8OqQC3GgA2NyZAmJKh8ewIJ2ikKlNg== Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'modify': 0.04; 'subject:Python': 0.05; '(even': 0.05; 'python3': 0.05; '-use': 0.07; 'append': 0.07; 'assignment': 0.07; 'attributes': 0.07; 'key.': 0.07; 'subject:file': 0.07; "'''": 0.09; "'name':": 0.09; '-my': 0.09; 'dict': 0.09; 'iterate': 0.09; 'loop.': 0.09; 'percentage': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'subject:using': 0.09; 'example:': 0.10; 'python': 0.10; 'question.': 0.13; 'file,': 0.15; '(created': 0.16; '-create': 0.16; '.db': 0.16; 'add.': 0.16; 'attributes.': 0.16; 'caching': 0.16; 'dictionary.': 0.16; 'entry.': 0.16; 'key/value': 0.16; 'range(0,': 0.16; 'received:80.91.229.3': 0.16; 'received:dip0.t-ipconnect.de': 0.16; 'received:io': 0.16; 'received:plane.gmane.org': 0.16; 'received:psf.io': 0.16; 'received:t-ipconnect.de': 0.16; 'superfluous': 0.16; 'write.': 0.16; 'wrote:': 0.16; 'attribute': 0.18; 'nested': 0.18; '>>>': 0.20; 'changes': 0.20; 'fix': 0.21; 'trace': 0.22; 'file.': 0.22; 'trying': 0.22; 'needed.': 0.23; 'skip:l 40': 0.23; 'tried': 0.24; 'import': 0.24; 'written': 0.24; 'header:User-Agent:1': 0.26; "doesn't": 0.26; 'header:X-Complaints-To:1': 0.26; 'linux': 0.26; 'appreciated.': 0.27; 'figure': 0.27; 'error': 0.27; '2.0': 0.27; 'turns': 0.27; "skip:' 10": 0.28; 'values': 0.28; 'convenience': 0.29; 'dictionary': 0.29; 'code': 0.30; 'error.': 0.31; 'skip:s 30': 0.31; 'skip:d 40': 0.32; 'problem': 0.33; 'extract': 0.33; 'open': 0.33; 'file': 0.34; 'this?': 0.34; 'skip:d 20': 0.34; 'add': 0.34; 'step': 0.36; 'but': 0.36; 'there': 0.36; 'guidance': 0.36; 'to:addr:python-list': 0.36; 'subject:?': 0.36; 'subject:: ': 0.37; 'received:org': 0.37; 'available.': 0.37; 'skip:s 40': 0.38; 'thank': 0.38; 'data': 0.39; 'format': 0.39; 'subject:the': 0.39; 'to:addr:python.org': 0.40; 'subject:with': 0.40; 'received:de': 0.40; 'called': 0.40; 'hello,': 0.40; 'some': 0.40; 'future': 0.60; 'your': 0.60; 'back': 0.62; 'more': 0.63; 'to,': 0.63; 'information': 0.63; 'here': 0.66; 'forward': 0.66; 'therefore': 0.67; "'2',": 0.84; 'but!': 0.84; 'object:': 0.84; 'writing.': 0.84; '50+': 0.91 X-Injected-Via-Gmane: http://gmane.org/ X-Gmane-NNTP-Posting-Host: p57bd886f.dip0.t-ipconnect.de User-Agent: KNode/4.13.3 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20+ Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Xref: csiph.com comp.lang.python:100712 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.