After we create a database file using shelve.open and then close the program, if we run the code again, but with different input(s), it actually replaces the text instead of appending it.
How may I change this behavior?
For example:
db = shelve.open('store')
db['some variable'] = some value
db['another variable'] = another value
db.close()
And now when we write the same code but with different values for the same variable, we replace the previous value instead of appending the values to it. How can I change that?
Assuming your values are lists:
Use db = shelve.open('store',writeback=True) and then append the value to the same key.
Since your code does not open 'store' with writeback=True you
must assign a variable the value of the key, temp = db['some variable'], which would be
some value, and then append that variable, temp.append(another
value), and then reassign that keys value, db['some variable'] =
temp.
Should not your third line of code be db['some variable'] = another value' in order to replace the value?
Edit: Other possible meaning of question?
Do you mean you want to load the database into your object and continue to use your "UI" code to edit it after closing the program? If so then you can do something like:
class Update_MyStore(MyStore):
def __init__(self, store):
db = shelve.open(store)
for i in db:
setattr(self, i, db[i])
self.items()
self.store_in_db()
Update_MyStore('store')
Edit: Another option to update, if that is the case, if you want to add or update specific items:
while True:
store = shelve.open('store',writeback = True)
Item = input('Enter an item: ').capitalize() #I prefer str(raw_input('Question '))
if not Item or Item == 'Break':
break
store['item_quantity'][Item] = int(input(('Enter the number of {0} available in the store: ').format(Item)))
store['item_rate'][Item] = float(input(('Enter the rate of {0}: ').format(Item)))
store.sync()
store.close()
Related
I have some code which is something along the lines of
storage = {}
for index, n in enumerate(dates):
if n in specific_dates:
for i in a_list:
my_dict[i] = {}
my_dict[i]["somthing"] = value
my_dict[i]["somthing2"] = value_2
else:
#print(storage[dates[index - 1]["my_dict"][i]["somthing"])
for i in a_list:
my_dict[i] = {}
my_dict[i][somthing] = different_value - storage[dates[index - 1]["my_dict"][i]["somthing"]
my_dict[i]["somthing2"] = different_value_2
storage[n]["my_dict"] = my_dict
The first pass will initiate the code in if n in specific_dates: the second pass goes to for i in a_list:
Essentially the code is getting a value set on specific dates and this value is then used for nonspecific dates that occur after the specific date until the next specific date overrides that value. However, at every date, i save a dictionary of values within a master dictionary called storage.
I found the problem which is when I print my_dict on the second pass my_dict[i] is literally an empty dictionary whereas prior to that loop it was filled. Where I have put the commented-out print line it would print value. I have fixed this by changing storage[n]["my_dict"] = my_dict to storage[n]["my_dict"] = my_dict.copy() and can now access value.
However, I do not really understand why this didnt work how I expected in the first place as I thought by assigning my_dict to storage it was creating new memory.
I was hoping someone could explain why this is happening and why storage[dates[index - 1]["my_dict"][i]["somthing"] doesn't create a new space in memory if that is indeed what is happening.
I have a script where I read a file line by line and save some information to lists and dictionary. Namely, I store the keys (say ley1 and key2) to pass to the dictionary and a list to be stored as item in the dictionary.
It happens that I have to update a dictionary only if some conditions are met, i.e.:
myDict = {}
if mylist:
myDict[key1][key2] = mylist
Of course this will raise a KeyError if key2 does not exist already. Therefore, I introduced the following function:
def updateDict2keys(myDict,mykey1,mykey2,myitems):
"""
updates a dictionary by appending values at given keys (generating key2 if not given)
input: key1, key2 and items to append
output: dictionary orgnanized as {mykey1:{mykey2:myitems}}
"""
try:
myDict[mykey1][mykey2] = myitems
except KeyError:
myDict[mykey1] = {mykey2:myitems}
# output
return myDict
My question is: is it "safe" to call such a function in the main code inside a for loop like this?
with open(os.path.join(path+myfile)) as ntwkf:
# read file
rdlistcsv = csv.reader(ntwkf)
rowslist = [line for line in rdlistcsv]
ntwkJuncDict = {}
for idx,f in enumerate(rowslist): # loop over file lines
if f:
lineelmnt = f[0].split()[0]
else:
continue
# flags
isBranchName = True if lineelmnt=='definitions' else False
isJunction = True if lineelmnt=='connections' else False
# update dictionary
if isBranchName:
reachname = f[0].split()[2].replace("'","")
if isJunction:
usreach = f[0].split()[2].replace("'","")
uschain = float(f[1].replace("'","").replace(" ",""))
if usreach:
uslist = [usreach, uschain]
todivide.append(uslist)
ntwkJuncDict = updateDict2keys(ntwkJuncDict, reachname, 'upstream', uslist)
I must say, my code works pretty well, I am just asking myself (and yourselves of course!) if I am doing everything the python way and if there are smarter solutions.
Instead of accessing the primary key, use dict.setdefault with a default empty dict on it.
def updateDict2keys(myDict,mykey1,mykey2,myitems):
myDict.setdefault(mykey1, {})[mykey2] = myitems
return myDict
Note that your initial approach is also safe. Only lookup, not assignment, throws KeyError. In the statement myDict[mykey1][mykey2] = myitems, a KeyError can only be thrown of mykey1 is not set. Thus, setting it to an empty dict on a KeyError does not overwrite anything.
In this function I'm reading from a .txt file, and store the values in a dictionary. I want to be able to pass this dictionary to another function, to do further calculations and sorting.
I can manage to print all rows from the .txt file, but that's it.
Return breaks the loop and only gives the first row.
Global variables and nested functions are bad form.
Have tried to use yield (for the first time), but that only prints "generator object get_all_client_id at 0x03369A20"
file_with_client_info = open("C:\\Users\\clients.txt", "r")
def get_all_client_id():
client_details = {}
for line in file_with_client_info:
element = line.split(",")
while element:
client_details['client_id'] = element[0]
client_details['coordinates'] = {}
client_details['coordinates']['lat'] = element[1]
client_details['coordinates']['long'] = element[2]
break
print(client_details)
There are a few errors in you code.
Use a return statement to output the dictionary.
The while-loop does not loop as you are breaking on the first iteration. Use an if-statement to check if the line is empty instead.
The last entries in the client_details dict are overwritten on each iteration. Create a new entry instead, probably using the client_id as key.
It is recommended you use a with context manager to open your file.
It is preferable to provide the name of your file to your function and let it open it instead of having a globally opened file.
Here is a fixed version of your code.
def get_all_client_id(file):
client_details = {}
with open(file, 'r') as f:
for line in f:
element = line.strip().split(',')
if element:
client_id, lat, long, *more = element
client_details[client_id] = {'lat': lat, 'long': long}
return client_details
clients_dict = get_all_client_id("C:\\Users\\clients.txt")
I am quite new to Python and am just trying to get my head around some basics.
I was wondering if anyone could show me how to perform the following tasks. I have a text file with multiple lines, those lines are as follows:
name1, variable, variable, variable
name2, variable, variable, variable
name3, variable, variable, variable
I want to store these items in a dictionary so they can be easily called. I want the name to be the key. I then want to be able to call the variables like this: key[0] or key1
The code I have at the moment does not do this:
d = {}
with open("servers.txt") as f:
for line in f:
(key, val) = line.split()
d[int(key)] = val
Once this is done, I would like to be able to take an input from a user and then check the array to see if this item is present in the array. I have found a few threads on Stackoverflow however none seem to do what I require.
There is a Similar Question asked here.
Any assistance you can provide would be amazing. I am new to this but I hope to learn fast & start contributing to threads myself in the near future :)
Cheers!
You're nearly there. Assuming that .split() actually splits the lines correctly (which it wouldn't do if there are actual commas between the values), you just need an additional unpacking operator (*):
d = {}
with open("servers.txt") as f:
for line in f:
key, *val = line.split() # first element -> key, rest -> val[0], val[1] etc.
d[int(key)] = val
If you want to check if a user-entered key exists, you can do something like
ukey = int(input("Enter key number: "))
values = d.get(ukey)
if d is not None:
# do something
else:
print("That key doesn't exist.")
Suppose that your file my_file.csv looks like:
name1, variable, variable, variable
name2, variable, variable, variable
name3, variable, variable, variable
Use pandas to do the work:
import pandas as pd
result = pd.read_csv('my_file.csv', index_col=0, header=None)
print(result)
print(result.loc['name1'])
Notice that pandas is a 3rd party library, and you need to install it using pip or easy_install tools.
In my python script, I am itterating through a list (headerRow) starting at index 9. I want to check to see if it is already in the database, and if not then add it to a database with an auto-incementing primary key. I then want to send it through the loop again to retrieve it's primary key.
for i in range (9, len(headerRow)):
# Attempt to retrieve an entry's corresponding primary key.
row = cursor.fetchone()
print i
if row == None: # New Entry
# Add entry to database
print "New Entry Added!"
i -= 1 # This was done so that it reiterates through and can get the PK next time.
print i
else: # Entry already exists
print "Existing Entry"
qpID = row[0]
# ...
Here is the output of my script:
9
New Question Added!
8
10
New Question Added!
9
11
As you can see, my issue is that range() doesn't care what the existing value of i is. What is the preferred python way to do what I'm trying to do?
Thanks in advance,
Mike
Why not use a while loop?
i=9
while (i<len(headerRow)):
# Attempt to retrieve an entry's corresponding primary key.
row = cursor.fetchone()
if row == None: # New Entry
# Add entry to database
print "New Entry Added!"
else: # Entry already exists
print "Existing Entry"
qpID = row[0]
i += 1
# ...
My great distaste for manually changing index variables makes me want to comment on this... :)
How about just changing it to do both things in the same iteration?
Code looks a little strange, but you get the idea.
for i in range (9, len(headerRow)):
# Attempt to retrieve an entry's corresponding primary key.
row = cursor.fetchone()
print i
if row == None: # New Entry
# Add entry to database
print "New Entry Added!"
row = cursor.fetchone() # re-fetch to get the PK
# Entry will exist now
print "Getting Existing Entry"
qpID = row[0]
# ...
And to try to explain why decrementing the "i" doesn't work:
The for loop doesn't really increment the variable. It simply picks the next value from the sequence you gave it (generated by the range function). So if the secquence is [9,10,11,12] it will pick those, in order. The variable "i" will get the next value and the previous will be discarded. No increment or decrement will affect this.