How to update dictionary on python? - python

So I'm working with creating a master dictionary while running a query for individual information.
Currently I have:
dictionary = {}
user_input =input('enter user id: ')
D = query(user_input)
dictionary[user_input] = D
And if I print dictionary[user_input] = D, I will get something like this:
{'user_input':[info]}
I want to prompt repeatedly and save all the individual information in one master dictionary and put it into a textfile.
How do I format my print so that when I try to print it to the textfile it's all written as one big dictionary?
What I've tried:
output_file = ('output.txt', 'w')
print(dictionary, file = output_file)
output_file.close()
This only seems to print {}
EDIT: Tried something diff.
Since D already returns a dictionary, I tried:
dictionary.update(D)
Which is supposed to add the dictionary that is stored in D to the dictionary right?
However, when I try printing dictionary:
print(dictionary)
#it returns: {}

Use json.dump to write to the file. Then you can use json.load to load that data back to a dictionary object.
import json
with open('dictionary.txt', 'w') as f:
json.dump(dictionary, f)
https://docs.python.org/3/library/json.html
EDIT: since you cannot use json maybe you can just separate the questions and answers with new lines like this. That will also be easy and clean to parse later:
with open('dictionary.txt', 'w') as f:
for k,v in dictionary.items():
f.write('%s=%s\n' % (k, v,))

Not totally familiar with the issue, so I'm not sure if this is what you're looking for. But you don't need to print the assignment itself in order to get the value. You can just keep adding more things to the dictionary as you go, and then print the whole dictionary to file at the end of your script, like so:
dictionary = {}
user_input =input('enter user id: ')
D = query(user_input)
dictionary[user_input] = D
# do this more times....
# then eventually....
print(dictionary)
# or output to a file from here, as described in the other answer

Related

Creating a function to concatenate strings based on len(array)

I am trying to concatenate a string to send a message via python>telegram
My plan is so that the function is modular.
It first import lines from a .txt file and based on that many lines it creates two different arrays
array1[] and array2[], array1 will receive the values of the list as strings and array2 will receive user generated information to complemente what is stored in the same position as to a way to identify the differences in the array1[pos], as to put in a way:
while (k<len(list)):
array2[k]= str(input(array1[k]+": "))
k+=1
I wanted to create a single string to send in a single message like however in a way that all my list goes inside the same string
string1 = array1[pos]+": "+array2[pos]+"\n"
I have tried using while to compared the len but I kept recalling and rewriting my own string again and again.
It looks like what you're looking for is to have one list that comes directly from your text file. There's lots of ways to do that, but you most likely won't want to create a list iteratively with the index position. I would say to just append items to your list.
The accepted answer on this post has a good reference, which is basically the following:
import csv
with open('filename.csv', 'r') as fd:
reader = csv.reader(fd)
for row in reader:
# do something
Which, in your case would mean something like this:
import csv
actual_text_list = []
with open('filename.csv', 'r') as fd:
reader = csv.reader(fd)
for row in reader:
actual_text_list.append(row)
user_input_list = []
for actual_text in actual_text_list:
the_users_input = input(f'What is your response to {actual_text}? ')
user_input_list.append(the_users_input)
This creates two lists, one with the actual text, and the other with the other's input. Which I think is what you're trying to do.
Another way, if the list in your text file will not have duplicates, you could consider using a dict, which is just a dictionary, a key-value data store. You would make the key the actual_text from the file, and the value the user_input. Another technique, you could make a list of lists.
import csv
actual_text_list = []
with open('filename.csv', 'r') as fd:
reader = csv.reader(fd)
for row in reader:
actual_text_list.append(row)
dictionary = dict()
for actual_text in actual_text_list:
the_users_input = input(f'What is your response to {actual_text}? ')
dictionary[actual_text] = the_users_input
Then you could use that data like this:
for actual_text, user_input in dictionary.items():
print(f'In response to {actual_text}, you specified {user_input}.')
list_of_strings_from_txt = ["A","B","C"]
modified_list = [f"{w}: {input(f'{w}:')}" for w in list_of_strings_from_txt]
I guess? maybe?

How to store regex in dictionary python?

How to store regex inside dictionary. I have a text file stored in my computer and I wanna go trough it line by line. I need to use regex to get some information. So far I'm good. My problem is I do not know how to store it in dictionary. Only the information that I need, not the other stuff that comes with it.
I want to safe the data in key while value how many time appeared
input syslog.log ... output email address and how many time appeard
You can use below approach first read the file and create empty dictionary. An for each line check if that line is alreday in dictionary increment the value else intialize the value with 1.
d = {}
with open('input.txt', 'r') as fp:
for data in fp.readlines():
data = data.strip()
if data in d:
d[data] += 1
else:
d[data] = 1
print(d)

How to write output with fout function in properly?

I'm trying to read and write a file with python file system but I'm having some problems. I believe that the reading/opening function is correct but the writing one is giving me a hard time.
I'm doing it inside a function that inverts a dictionary and I want it to read the dictionary from a text file instead of doing it inside the code, here's how I called it(not beautifully but works):
d = fin = open('dict.txt')
However, when it comes to writing the inverted dictionary to a file I'm failing miserably. The function call that prints the inverted dict is invert_dict(d) so I thought that I should try to write it like this:
invert_dict(d) = fout = open('output.txt', 'w')
Which is clearly wrong but that's what I got from reading a book. Here's my raw invert dictionary function :
def invert_dict(d):
print(' the dictionary is \n' , d)
inverse = dict()
for key in d:
val = d[key]
for i in val:
if i not in inverse:
inverse[i] = [key]
else:
inverse[i].append(key)
return inverse
d={'vowels':['a','e','i','o','u'], 'letters':['a','b','c','d']}
print(invert_dict(d))
How should I improve my code? Thanks in advance.
Your code is pretty good, just using items to loop is better, and also setdefault is easier:
def invert_dict(d):
print(' the dictionary is \n' , d)
inverse = {}
for k,v in d.items():
for i in v:
inverse.setdefault(i,[]).append(k)
return inverse
edit:
Misunderstood before, so you should use:
import json
d = fin = json.loads(open('dict.txt'))
with open('output.txt', 'w') as fout:
fout.write(invert_dict(d))

Python 2 - iterating through csv with determinating specific lines as dicitonary

I generated csv from multiple dictionaries (to be readable and editable too) with help of this question. Output is simple
//Dictionary
key,value
key2,value2
//Dictionary2
key4, value4
key5, value5
i want double backslash to be separator to create new dictionary, but every calling csv.reader(open("input.csv")) evaluates through lines so i have no use of:
import csv
dict = {}
for key, val in csv.reader(open("input.csv")):
dict[key] = val
Thanks for helping me out..
Edit: i made this piece of.. well "code".. I'll be glad if you can check it out and review:
#! /usr/bin/python
import csv
# list of dictionaries
l = []
# evalute throught csv
for row in csv.reader(open("test.csv")):
if row[0].startswith("//"):
# stripped "//" line is name for dictionary
n = row[0][2:]
# append stripped "//" line as name for dictionary
#debug
print n
l.append(n)
#debug print l[:]
elif len(row) == 2:
# debug
print "len(row) %s" % len(row)
# debug
print "row[:] %s" % row[:]
for key, val in row:
# print key,val
l[-1] = dic
dic = {}
dic[key] = val
# debug
for d in l:
print l
for key, value in d:
print key, value
unfortunately i got this Error:
DictName
len(row) 2
row[:] ['key', ' value']
Traceback (most recent call last):
File "reader.py", line 31, in <module>
for key, val in row:
ValueError: too many values to unpack
Consider not using CSV
First of all, your overall strategy to the data problem is probably not optimal. The less tabular your data looks, the less sense it makes to keep it in a CSV file (though your needs aren't too far out of the realm).
For example, it would be really easy to solve this problem using json:
import json
# First the data
data = dict(dict1=dict(key1="value1", key2="value2"),
dict2=dict(key3="value3", key4="value4"))
# Convert and write
js = json.dumps(data)
f = file("data.json", 'w')
f.write(js)
f.close()
# Now read back
f = file("data.json", 'r')
data = json.load(f)
print data
Answering the question as written
However, if you are really set on this strategy, you can do something along the lines suggested by jonrsharpe. You can't just use the csv module to do all the work for you, but actually have to go through and filter out (and split by) the "//" lines.
import csv
import re
def header_matcher(line):
"Returns something truthy if the line looks like a dict separator"
return re.match("//", line)
# Open the file and ...
f = open("data.csv")
# create some containers we can populate as we iterate
data = []
d = {}
for line in f:
if not header_matcher(line):
# We have a non-header row, so we make a new entry in our draft dictionary
key, val = line.strip().split(',')
d[key] = val
else:
# We've hit a new header, so we should throw our draft dictionary in our data list
if d:
# ... but only if we actually have had data since the last header
data.append(d)
d = {}
# The very last chunk will need to be captured as well
if d:
data.append(d)
# And we're done...
print data
This is quite a bit messier, and if there is any chance of needed to escape commas, it will get messier still. If you needed, you could probably find a clever way of chunking up the file into generators that you read with CSV readers, but it won't be particularly clean/easy (I started an approach like this but it looked like pain...). This is all a testament to your approach likely being the wrong way to store this data.
An alternative if you're set on CSV
Another way to go if you really want CSV but aren't stuck on the exact data format you specify: Add a column in the CSV file corresponding to the dictionary the data should go into. Imagine a file (data2.csv) that looks like this:
dict1,key1,value1
dict1,key2,value2
dict2,key3,value3
dict2,key4,value4
Now we can do something cleaner, like the following:
import csv
data = dict()
for chunk, key, val in csv.reader(file('test2.csv')):
try:
# If we already have a dict for the given chunk id, this should add the key/value pair
data[chunk][key] = val
except KeyError:
# Otherwise, we catch the exception and add a fresh dictionary with the key/value pair
data[chunk] = {key: val}
print data
Much nicer...
The only good argument for doing something closer to what you have in mind over this is if there is LOTS of data, and space is a concern. But that is not very likely to be case in most situations.
And pandas
Oh yes... one more possible solution is pandas. I haven't used it much yet, so I'm not as much help, but there is something along the lines of a group_by function it provides, which would let you group by the first column if you end up structuring the data as in the the 3-column CSV approach.
I decided to use json instead
Reading this is easier for the program and there's no need to filter text. For generating the data inside database in external file.json will serve python program.
#! /usr/bin/python
import json
category1 = {"server name1":"ip address1","server name2":"ip address2"}
category2 = {"server name1":"ip address1","server name1":"ip address1"}
servers = { "category Alias1":category1,"category Alias2":category2}
js = json.dumps(servers)
f = file("servers.json", "w")
f.write(js)
f.close()
# Now read back
f = file("servers.json", "r")
data = json.load(f)
print data
So the output is dictionary containing keys for categories and as values are another dictionaries. Exactly as i wanted.

Writing a dictionary to a csv file with one line for every 'key: value'

I've got a dictionary:
mydict = {key1: value_a, key2: value_b, key3: value_c}
I want to write the data to a file dict.csv, in this style:
key1: value_a
key2: value_b
key3: value_c
I wrote:
import csv
f = open('dict.csv','wb')
w = csv.DictWriter(f,mydict.keys())
w.writerow(mydict)
f.close()
But now I have all keys in one row and all values in the next row..
When I manage to write a file like this, I also want to read it back to a new dictionary.
Just to explain my code, the dictionary contains values and bools from textctrls and checkboxes (using wxpython). I want to add "Save settings" and "Load settings" buttons.
Save settings should write the dictionary to the file in the mentioned way (to make it easier for the user to edit the csv file directly), load settings should read from the file and update the textctrls and checkboxes.
The DictWriter doesn't work the way you expect.
with open('dict.csv', 'w') as csv_file:
writer = csv.writer(csv_file)
for key, value in mydict.items():
writer.writerow([key, value])
To read it back:
with open('dict.csv') as csv_file:
reader = csv.reader(csv_file)
mydict = dict(reader)
which is quite compact, but it assumes you don't need to do any type conversion when reading
Just to give an option, writing a dictionary to csv file could also be done with the pandas package. With the given example it could be something like this:
mydict = {'key1': 'a', 'key2': 'b', 'key3': 'c'}
import pandas as pd
(pd.DataFrame.from_dict(data=mydict, orient='index')
.to_csv('dict_file.csv', header=False))
The main thing to take into account is to set the 'orient' parameter to 'index' inside the from_dict method. This lets you choose if you want to write each dictionary key in a new row.
Additionaly, inside the to_csv method the header parameter is set to False just to have only the dictionary elements without annoying rows. You can always set column and index names inside the
to_csv method.
Your output would look like this:
key1,a
key2,b
key3,c
If instead you want the keys to be the column's names, just use the default 'orient' parameter that is 'columns', as you could check in the documentation links.
Considering the comment from #Rabarberski, when using orient='columns you should configure data as follows:
d = {k: [v] for k, v in mydict.items()}
Easiest way is to ignore the csv module and format it yourself.
with open('my_file.csv', 'w') as f:
[f.write('{0},{1}\n'.format(key, value)) for key, value in my_dict.items()]
outfile = open( 'dict.txt', 'w' )
for key, value in sorted( mydict.items() ):
outfile.write( str(key) + '\t' + str(value) + '\n' )
Can you just do:
for key in mydict.keys():
f.write(str(key) + ":" + str(mydict[key]) + ",");
So that you can have
key_1: value_1, key_2: value_2
I've personally always found the csv module kind of annoying. I expect someone else will show you how to do this slickly with it, but my quick and dirty solution is:
with open('dict.csv', 'w') as f: # This creates the file object for the context
# below it and closes the file automatically
l = []
for k, v in mydict.iteritems(): # Iterate over items returning key, value tuples
l.append('%s: %s' % (str(k), str(v))) # Build a nice list of strings
f.write(', '.join(l)) # Join that list of strings and write out
However, if you want to read it back in, you'll need to do some irritating parsing, especially if it's all on one line. Here's an example using your proposed file format.
with open('dict.csv', 'r') as f: # Again temporary file for reading
d = {}
l = f.read().split(',') # Split using commas
for i in l:
values = i.split(': ') # Split using ': '
d[values[0]] = values[1] # Any type conversion will need to happen here
#code to insert and read dictionary element from csv file
import csv
n=input("Enter I to insert or S to read : ")
if n=="I":
m=int(input("Enter the number of data you want to insert: "))
mydict={}
list=[]
for i in range(m):
keys=int(input("Enter id :"))
list.append(keys)
values=input("Enter Name :")
mydict[keys]=values
with open('File1.csv',"w") as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=list)
writer.writeheader()
writer.writerow(mydict)
print("Data Inserted")
else:
keys=input("Enter Id to Search :")
Id=str(keys)
with open('File1.csv',"r") as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
print(row[Id]) #print(row) to display all data
Have you tried to add the "s" on: w.writerow(mydict) like this: w.writerows(mydict)? This issue happened to me but with lists, I was using singular instead of plural.

Categories

Resources