Unable to write condition to update dictionary value in python - python

Please help! How can I write condition in my existing code which will check as below. Please look commented block. I can't append value in the dictionary/list. What do I need to write/change?
When user come back to main menu and run encryption process again using same key file but save the encrypted file in different name. User can create as many encrypted file using same key.
My try:
import Encrypt
from collections import defaultdict
key_value_dict = {}
def encrypt_file():
try:
txtfile = input("Your plain txt file that you want to encrypt : ")
encrypt_file = input("Directory to save the encrypted file : ")
key = input("Key for encryption : ")
# process for encryption
Encrypt.encrypt_file(txtfile, encrypt_file, key)
# ----------------------------------------------------------------
key_value_dict = defaultdict(list, {key: encrypt_file})
print(key_value_dict)
key_value_dict [key].append(encrypt_file)
print(key_value_dict )
# --------------------------------------------------------------------
except FileNotFoundError:
print("File Not Found!")
def menu():
selection = True
while selection:
print("""
MAIN MENU:
[1] Encrypt files using existing keys.
[2] Exit.
""")
try:
selection = input("Please select : ")
if selection == "1":
encrypt_file() # call function
elif selection == "2":
print("\n[4] Keys are used for encryption:", "\n", key_value_dict)
selection = None
else:
print("\n Invalid selection! Try again")
except ValueError:
print("\n Exception: Invalid user input!")
# Main function
if __name__ == '__main__':
menu()

If I understand correctly I don't think you need defaultdict
Try this:
# define this first outside the function like you have
encrypt_key_value_dict = {}
# Within your code block, get rid of the assignment to default dict
if encrypt_key_value_dict[key]:
encrypt_key_value_dict.append(encrypt_file)
else:
encrypt_key_value_dict[key] = [encrypt_file]
I can't see from your code where you keys are getting passed etc but I am sure you can figure that out.

Related

How to append to csv file before script is done running?

I am currently making a log in system which stores usernames and passwords in a text file.
This is my code:
import csv
Brugere = open("D:\Filer\Programmering/Profiles.txt","r+",newline="\n")
writer = csv.writer(Brugere, delimiter=",")
print("Welcome to the chat app!")
Brugernavn = "" //means username
Kodeord = "" // means password
def Signup(j,k):
print("Welcome to sign up!\n Please enter your Username")
j = input("")
if j not in Brugere:
print("Hello, " + j + ", please enter a password:")
k = input("")
line1 = [j,k]
writer.writerow(line1)
print("Great! Now you can sign in")
Signin(Brugernavn, Kodeord)
else:
print("Username already taken! try again")
Signup(Brugernavn, Kodeord)
def Signin(U,P):
print("Welcome to sign in!")
print("Do you already have an account?[y/n]")
ans = input("")
if ans == "n":
print("You will now be redirected to sign up")
Signup(Brugernavn, Kodeord)
elif ans == "y":
U = input("Username: ")
if U in Brugere:
P = input("Password: ")
print("WELCOME")
else:
print("Invalid username, try again")
Signin(Brugernavn, Kodeord)
else:
print("Please write 'y' or 'n'")
Signin(Brugernavn, Kodeord)
Signin(Brugernavn, Kodeord)
Brugere.close()
When I run it, the signup function works as it should, but when the signin function is called, it can't find the username and password from the text file. I think it's because they only get appended after the script is done running. However, 'Im not sure.
I've been struggling for a long time with this csv file thing. I want to have it like
this where each line is a list where I can find the username and password
I've heard people calling it "comma seperated values", however I have no idea how to do it.
TL;DR:
I suspect the simplest solution is:
...
if j not in brugere:
...
writer.writerow(line1)
brugere.flush() # Flush pending changes to file.
...
...
However, I've noticed a few things worthy of consideration:
Python help. You can get help on Python things within an interactive Python session:
python
> import csv
> help(csv)
CSV for this sort of usecase isn't a good idea. If it's production grade use a proper DB, if you're just playing around locally to get a feel for Python use a dict() and store as JSON. I.e.:
import json
username = "myuser"
password = "password"
filename = "data.json"
# Reads data. Requires file `data.json` to exist, with content `{}`.
with open(filename, "r") as data_stream:
data = json.load(data_stream)
if username in data:
print(f"User {username} exists.")
else:
data[username] = password # You'd usually hash and salt a password. It's a separate topic.
# Writes data to disk.
with open(filename, "w") as data_stream:
data_stream.write(json.dumps(data, indent=2)) # Makes it look pretty on disk.
Note that open() returns a stream wrapped in class io.TextIOWrapper (see python -c "import io; help(io.TextIOWrapper)"). It's basically an interface to get the data you want, not the data itself. Try open("test.txt").readlines() to actually read data from stream, for example. Note that streams are consumables.
When you call in on the stream Brugere you're calling the __contains__() dunder method on class io.TextIOWrapper which isn't implemented. But Python being Python it returns False (it's not meaningful).
The CSV interfaces are pretty straightforward:
import csv
filename = "test.txt"
f = open(filename, "w")
writer = csv.writer(f)
writer.write(["myuser", "password"])
# Flushes lines to file.
f.flush()
...
f.close()
Creating a CSV is as simple as writing a string with each value separated by a designated character, often a comma as the name implies. You don't really need the csv library for that.
Your Signup method would then look as follows:
def Signup(j,k):
print("Welcome to sign up!\n Please enter your Username")
j = input("")
if j not in Brugere:
print("Hello, " + j + ", please enter a password:")
k = input("")
line1 = [j,k]
# Write a string with a comma between the values
Brugere.write("{}, {}\n".format(j, k))
print("Great! Now you can sign in")
Signin(Brugernavn, Kodeord)
else:
print("Username already taken! try again")
Signup(Brugernavn, Kodeord)
With that being said, using CSVs to store operational data in a an application does not make all that much sense to me. Please see below for a modified version of signup using SQLite, which is much more robust and still simple to use:
import sqlite3
con = sqlite3.connect('brugere.db')
cur = con.cursor()
# Create a user table with bruger and kodeord
# I added an extra field for when the user was created as well
# which defaults to the date and time the user was created
cur.execute("""create table if not exists brugere
(brugernavn text,
kodeord text,
dato_oprettet TIMESTAMP DEFAULT CURRENT_TIMESTAMP)""")
con.close()
def signup():
con = sqlite3.connect('brugere.db')
cur = con.cursor()
with con:
print("Please enter your Username")
bruger = input()
cur.execute("select brugernavn from brugere where brugernavn =?", [bruger])
bruger_eksisterer = cur.fetchone()
if bruger_eksisterer:
print("Username already taken! Try again")
# Signup(Brugernavn, Kodeord)
else:
print("Hello, " + bruger + ", please enter a password:")
kodeord = input()
try:
cur.execute("insert into brugere (brugernavn, kodeord) values (?, ?)", (bruger, kodeord))
print("Great! Now you can sign in")
except sqlite3.Error as Err:
print("Couldn't add user.\nError: {}".format(Err))
# Signin(Brugernavn, Kodeord)
con.close()
signup()
Modifying the signin should be straighforward, but I'll leave that part up to you.

How to jump back to a specific line of code (Python)

I just pulled out some old code but I'm curious to know how to jump back to a specific line of code. What I mean by this is that if there is an if statement, it will do something unless told otherwise, anyways, what I want to do is when the if statement ends, or when I get to the else bit, I want the code to not start all over again but start at a certain line in the code. I will explain more below:
CODE:
def main():
abc = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
message = input("What's the message to encrypt/decrypt? ")
def keyRead():
try:
return int(input("What number would you like for your key value? "))
except ValueError:
print("You must enter a number!")
main()
key = keyRead()
choice = input("Choose: encrypt or decrypt. ")
if choice == "encrypt":
encrypt(abc, message, key)
elif choice == "decrypt":
encrypt(abc, message, key * (-1))
else:
print("You must chose either 'encrypt' or 'decrypt!'")
main()
def encrypt(abc, message, key):
cipherText = ""
for letter in message:
if letter in abc:
newPosition = (abc.find(letter) + key * 2) % 52
cipherText += abc[newPosition]
else:
cipherText += letter
print(cipherText)
return cipherText
main()
So what I want really is that if the user doesn't input encrypt or decrypt it will show them the message: You must enter either 'encrypt' or 'decrypt'! but under this line I want it to go back to the choice part and not all the way back to the message part. If there is a way to do this I would really appreciate you helping me out!!
albeit loop best suited your case, but you really could jump back to a specific line:
import sys
def jump(lineno):
frame = sys._getframe().f_back
called_from = frame
def hook(frame, event, arg):
if event == 'line' and frame == called_from:
try:
frame.f_lineno = lineno
except ValueError as e:
print "jump failed:", e
while frame:
frame.f_trace = None
frame = frame.f_back
return None
return hook
while frame:
frame.f_trace = hook
frame = frame.f_back
sys.settrace(hook)
use this function to jump back to line key = keyRead().
besides, there are goto implementation in the wild.

How to write to a text file using iteration?

My code does not write to a file, what am I doing wrong? I am trying to program to continue to ask for products until the user does not enter a product code. I want all products to be saved in the file.
store_file = open("Database.txt", "w")
NewProduct = ""
while NewProduct != False:
contine = input("Press 1 to enter a new product press 2 to leave: ")
if contine == "1":
print("Enter your product information")
information = []
product = input("What's the product code: ")
information.append(product)
description = input("Give a description of the product: ")
information.append(description)
price = input("Enter price of product: ")
information.append(price)
information = str(information)
clean = information.replace("]","").replace("[","").replace(",","").replace("'","")
store_file.write(clean)
elif contine == "2":
NewProduct = False
else:
print("Your input is invalid")
store_file.close
I got the program working with the following adjustments. See comments for explanations:
store_file = open("Database.txt", "w")
NewProduct = ""
while NewProduct != False:
continue = raw_input("Press 1 to enter a new product press 2 to leave: ")
#Changed to raw_input because input was reading in an integer for 1 rather than a
#string like you have set up. This could be specific to my IDE
if continue == "1":
print("Enter your product information")
information = []
product = raw_input("What's the product code: ")
information.append(product)
description = raw_input("Give a description of the product: ")
information.append(description)
price = raw_input("Enter price of product: ")
information.append(price)
information = str(information)
clean = information.replace("]","").replace("[","").replace(",","").replace("'","")
store_file.write(clean + "\n")
#Added a line break at the end of each file write
elif contine == "2":
NewProduct = False
else:
print("Your input is invalid")
store_file.close() #Added parentheses to call the close function
I'm assuming the problem here is that you're using Python 2, and input isn't doing what you think it does. In Python 2, input evals the input as if it were Python source code, so if someone enters 2, it's going to return the int value 2, not "2". In Python 2, you want to use raw_input, always (eval-ing random user input not being secure/reliable).
Also, while on CPython (the reference interpreter) files tend to naturally close themselves when they go out of scope, you made an effort to close, but forgot to actually call the close method; store_file.close looks up the method without calling it, store_file.close() would actually close it. Of course, explicit close is usually the wrong approach; you should use a with statement to avoid the possibility of forgetting to close (or of an exception skipping the close). You can replace:
store_file = open("Database.txt", "w")
...
store_file.close()
with:
with open("Database.txt", "w") as store_file:
... do all your work that writes to the file indented within the with block ...
... When you dedent from the with block, the file is guaranteed to be closed ...
There are other issues though. What you're doing with:
information = str(information)
information = information.replace("]","").replace("[","").replace(",","").replace("'","")
is terrible. I'm 99% sure what you really wanted was to just join the inputs with spaces. If you switch all your input calls to raw_input (only on Python 2, on Python 3, input is like raw_input on Python 2), then your list is a list of str, and you can just join them together instead of trying to stringify the list itself, then remove all the list-y bits. You can replace both lines above with just:
information = ' '.join(information)

Having trouble parsing a txt file into a list full of zip codes in my zipcode lookup program

Hello everyone thanks for looking into my problem. What I am trying to do is write a "Structured" program in python that takes txt from a file and parses it into lists. Then after closing the file, I need to reference the user input (zipcode) in those lists and then print out the city and state according to the zipcode that they entered. My instructor is having us use structure by making several functions. I know there are probably lots of more efficient ways of doing this, but I must keep the structure thats in place.
EDIT
Here is my code(Current):
#-----------------------------------------------------------------------
# VARIABLE DEFINITIONS
eof = False
zipRecord = ""
zipFile = ""
zipCode = []
city = []
state = []
parsedList = []
#-----------------------------------------------------------------------
# CONSTANT DEFINITIONS
USERPROMPT = "\nEnter a zip code to find (Press Enter key alone to stop): "
#-----------------------------------------------------------------------
# FUNCTION DEFINITIONS
def startUp():
global zipFile
print "zipcode lookup program".upper()
zipFile = open("zipcodes.txt","r")
loadList()
def loadList():
while readRecord():
pass
processRecords()
def readRecord():
global eof, zipList, zipCode, city, state, parsedList
zipRecord = zipFile.readline()
if zipRecord == "":
eof = True
else:
parsedList = zipRecord.split(",")
zipCode.append(parsedList[0])
city.append(parsedList[1])
state.append(parsedList[2])
eof = False
return not eof
def processRecords():
userInput = raw_input(USERPROMPT)
if userInput:
print userInput
print zipCode
if userInput in zipCode:
index_ = zipcode.index(userInput)
print "The city is %s and the state is %s " % \
(city[index_], state[index_])
else:
print "\nThe zip code does not exist."
else:
print "Please enter a data"
def closeUp():
zipFile.close()
#-----------------------------------------------------------------------
# PROGRAM'S MAIN LOGIC
startUp()
closeUp()
raw_input("\nRun complete. Press the Enter key to exit.")
Here is a sample from the zipcode txt file:
00501,HOLTSVILLE,NY
I am definitely stuck at this point and would appreciate your help in this matter.
EDIT
Thanks for all the help everyone. I really do appreciate it. :)
why you fill the lists zipcode, city , state like that, i mean in each user entry we get the next line from the file
i think that you should do :
def loadList():
# Fill all the list first , make the readRecord() return eof (True or False).
while readRecord():
pass
# than process data (check for zip code) this will run it only one time
# but you can put it in a loop to repeat the action.
processRecords()
about your problem :
def processRecords():
userInput = raw_input(USERPROMPT)
# Check if a user has entered a text or not
if userInput:
# check the index from zipcode
if userInput in zipcode:
# the index of the zipcode in the zipcode list is the same
# to get related cities and states.
index_ = zipcode.index(userInput)
print "The city is %s and the state is %s " % \
(city[index_], state[index_])
else:
print "\nThe zip code does not exist."
else:
print "Please enter a data"
one of the beauties of Python is that it's interactive. if you take processRecords() out of loadList(), and then at the bottom of your program put:
if __name__ == '__main__':
processRecords()
Then, from the command prompt, type "python". You'll get the Python shell prompt, ">>>". There you type:
from zipcodes import * # this assumes your program is zipcodes.py
dir() # shows you what's defined
print zipCode # shows you what's in zipCode
that ought to help debugging.
Strings don't have an append method like lists do. What I think you're trying to do is append the strings zipCode, city, and state to parsedList. This is the code you'd use to do that:
parsedList.append(zipCode)
parsedList.append(city)
parsedList.append(state)
Or, even more compactly:
parsedList = [zipCode, city, state]
Let me know if you get another error message and I can offer more suggestions.

Personal archive tool, looking for suggestions on improving the code

i've written a tool in python where you enter a title, content, then tags, and the entry is then saved in a pickle file. it was mainly designed for copy-paste functionality (you spot a piece of code you like on the net, copy it, and paste it into the program), not really for handwritten content, though it does that with no problem.
i mainly did it because i'm always scanning through my pdf files, books, or the net for some coding example of solution that i'd already seen before, and it just seemed logical to have something where you could just put the content in, give it a title and tags, and just look it up whenever you needed to.
i realize there are sites online that handle this ex. http://snippets.dzone.com, but i'm not always online when i code. i also admit that i didn't really look to see if anyone had written a desktop app, the project seemed like a fun thing to do so here i am.
it wasn't designed with millions of entries in mind, so i just use a pickle file to serialize the data instead of one of the database APIs. the query is also very basic, only title and tags and no ranking based on the query.
there is an issue that i can't figure out, when you are at the list of entries there's a try, except clause where it tries to catch a valid index (integer). if you enter an inavlid integer, it will ask you to enter a valid one, but it doesn't seem to be able to assign it to the variable. if you enter a valid integer straightaway, there are no problems and the entry will display.
anyway let me know what you guys think. this is coded for python3.
main file:
#!usr/bin/python
from archive_functions import Entry, choices, print_choice, entry_query
import os
def main():
choice = ''
while choice != "5":
os.system('clear')
print("Mo's Archive, please select an option")
print('====================')
print('1. Enter an entry')
print('2. Lookup an entry')
print('3. Display all entries')
print('4. Delete an entry')
print('5. Quit')
print('====================')
choice = input(':')
if choice == "1":
entry = Entry()
entry.get_data()
entry.save_data()
elif choice == "2":
queryset = input('Enter title or tag query: ')
result = entry_query('entry.pickle', queryset)
if result:
print_choice(result, choices(result))
else:
os.system('clear')
print('No Match! Please try another query')
pause = input('\npress [Enter] to continue...')
elif choice == "3":
queryset = 'all'
result = entry_query('entry.pickle', queryset)
if result:
print_choice(result, choices(result))
elif choice == "4":
queryset = input('Enter title or tag query: ')
result = entry_query('entry.pickle', queryset)
if result:
entry = result[choices(result)]
entry.del_data()
else:
os.system('clear')
print('No Match! Please try another query')
pause = input('\npress [Enter] to continue...')
elif choice == "5":
break
else:
input('please enter a valid choice...')
main()
if __name__ == "__main__":
main()
archive_functions.py:
#!/bin/usr/python
import sys
import pickle
import os
import re
class Entry():
def get_data(self):
self.title = input('enter a title: ')
print('enter the code, press ctrl-d to end: ')
self.code = sys.stdin.readlines()
self.tags = input('enter tags: ')
def save_data(self):
with open('entry.pickle', 'ab') as f:
pickle.dump(self, f)
def del_data(self):
with open('entry.pickle', 'rb') as f:
data_list = []
while True:
try:
entry = pickle.load(f)
if self.title == entry.title:
continue
data_list.append(entry)
except:
break
with open('entry.pickle', 'wb') as f:
pass
with open('entry.pickle', 'ab') as f:
for data in data_list:
data.save_data()
def entry_query(file, queryset):
'''returns a list of objects matching the query'''
result = []
try:
with open(file, 'rb') as f:
entry = pickle.load(f)
os.system('clear')
if queryset == "all":
while True:
try:
result.append(entry)
entry = pickle.load(f)
except:
return result
break
while True:
try:
if re.search(queryset, entry.title) or re.search(queryset, entry.tags):
result.append(entry)
entry = pickle.load(f)
else:
entry = pickle.load(f)
except:
return result
break
except:
print('no entries in file, please enter an entry first')
pause = input('\nPress [Enter] to continue...')
def choices(list_result):
'''takes a list of objects and returns the index of the selected object'''
os.system('clear')
index = 0
for entry in list_result:
print('{}. {}'.format(index, entry.title))
index += 1
try:
choice = int(input('\nEnter choice: '))
return choice
except:
pause = input('\nplease enter a valid choice')
choices(list_result)
def print_choice(list_result, choice):
'''takes a list of objects and an index and displays the index of the list'''
os.system('clear')
print('===================')
print(list_result[choice].title)
print('===================')
for line in list_result[choice].code:
print(line, end="")
print('\n\n')
back_to_choices(list_result)
def back_to_choices(list_result):
print('1. Back to entry list')
print('2. Back to Main Menu')
choice = input(':')
if choice == "1":
print_choice(list_result, choices(list_result))
elif choice == "2":
pass
else:
print('\nplease enter a valid choice')
back_to_choices(list_result)
In the else, you call the main function again recursively. Instead, I'd do something like choice == "0", which will just cause the while loop to request another entry. This avoids a pointless recursion.

Categories