How do I save user input to a text file - python
I'm trying to create a personnal password vault. Basically I want to create a program that asks me what I want to do and depending on my input (New, or Access "title of website here") the program either lets me add a website title with it's corresponding username and password. Then in I type "Access..." i should get the username and password returned relative to the website's tite I input after the Access input. OFC all of this data is to be stored in a text file.
PROBLEM:
The problem is that when I check the text file, it stays blank. I tried changing the access mode (a, r, etc) and it doesn't work. Not only that, but the program returns only the last data entered, and not whichever data in select.
Keep in mind I'm a beginner.
Below is the code used:
vault = open("Passvault.txt", "a")
total = True
while total == True:
creation = True
action = input("What do you want to do? ")
if action == "New" or action == "new":
title = input("Add website: ")
username = input("Create username: ")
password = input("Create password: ")
vault.write("Title:" + username)
vault.write("\n")
vault.write("Username:" + username)
vault.write("\n")
vault.write("Password:" + password)
elif action == "Access " + title:
print(title)
print("Username: " + username)
print("Password: " + password)
creation = False
elif action == "Close":
creation = False
total = False
vault.close()
First of all, you are not reading the file. Reading AND writing in 'append' ('a') mode is a bad idea (see potential cursor issues).
I tested the code on Google Colab and it works. Note that the writing occurs only if you close the file.
Suggestions:
It is a good time to learn about databases. Even a simple Excel file would fit your goal better (check package csv).
Use 'a+' as the mode of opening the file: if the file does not exist, create it.
Try to open and close the file a bit more frequently, say, each time when you want to write something. Also with clause may be useful (https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files)
First of all, where do you define the variable title used in the elif condition. Another that how you are reading the file for title. Third and most important that your problem clearly mentions is that you are not seeing results being saved and that is because you don't close the file instantly and close method actually writes all data and saves the file in the end. Another way to save data before closing the file is by using the flush method.
Try this code:
vault = open("Passvault.txt", "a")
total = True
while total == True:
creation = True
action = input("What do you want to do? ")
if action.lower() == "new":
title = input("Add website: ")
username = input("Create username: ")
password = input("Create password: ")
vault.write("Title:" + username)
vault.write("\n")
vault.write("Username:" + username)
vault.write("\n")
vault.write("Password:" + password)
elif action == "Access " + title:
print(title)
print("Username: " + username)
print("Password: " + password)
creation = False
elif action == "Close":
creation = False
total = False
vault.close()
You didn't close the file at the end.
First of all you seem to be a bit confused how everything is working here so lets me clarify and then I will point out all the problems.
You first create a variable vault and assign it to file opened via append(a) mode.
Now append mode is used generally to append data, here you want to both read and write
data so you need to use read and write permission(r+).
Second , you are trying to create a vault and don't encrypt it any way. the problem is
that anyone can see it as a plain text by opening that file.
Now you set total to True and then use it for infinite while loop.
The problem here is that you can directly do while True so that loop continues
forever and you don't need to assign total a value of True because it doesn't need to
be changed as you can use break keyword to break out of loop. You just wasted memory
by assigning variable to True
Now inside the while loop, you create creation variable but never use it for a purpose, so it is I think not needed or you might have another plan and might use it in the future so I won't say about it.
Now you get input from the user and set it's value to action variable. This step is OK but I wan't to clarify that there are several security problems here but since they are very complex so I won't tell them here but this should be OK.
Now's the time of conditions:
Now in first if condition, you check is action == 'New or action == 'new', here you don't need to includeor` , although that's okay and there is no problem with it, you can do better. .lower() is a string method and it lower cases all the letters of the alphabet.
Either you can do if action.lower() in ['new' , 'create' , 'n' ....all inputs you want ] , note here you dont have to include '.....all inputs you want' , Its just to tell you that you need to put there all inputs on which you want the condition to be true.
Or you can simply do if action.lower() == 'new'
Now only if the condition is true this code runs
You create title variable and set it to user input, now here's too security problem but due to complexity I won't go into much deep. Always remember , wherever you have user interaction with application , there's a chance of security problem there.
Then you get the password and same problem. But also notice that you don't encrypt anything here. That's a big issue.
Now you write everything to the file but be aware that .write() doesn't write directly. You either have to call .flush() or close the file via .close() . But notice the problem , you called .close() but in the very end and out of the infinite while loop. You can tell that that close command is out of while loop by telling that both while loop and close are at the same level. If you have to put it inside while loop, you need to indent it a bit just like other code which is inside while loop. But that is also not gonna work because you close the file and you can't reuse it withot reopening it so either you put both open and close parts inside while loop or you use the .flush() method. This is the biggest bug due to which you are facing such a problem.
Now's the time of elif conditon
Here you see that in the condition you do if action == 'Access ' + title: and there are several problems here.
First you see that you directly compare action to access and you can do it better by using that list trich used in above if condition and can use .lower() method
Second that you use the title variable which notice only get defined when the above if condition runs. What if the above if condition doesn't run and what is the user directly said 'Access Google" or anything accept the above if condition such as "#^%&GJ" . Then elif condition will run and your variable title will not be found by python and then your program will crash. So it is better that you first search that if the input contains Access and the break it into Access And The keyword after it. There are several functions you can use like .strip() or others. Visit this link fore more methods.
Third, you are using the file cursor without being aware of it. Just like cursor in any text editor, the file handler also has a cursor which move foreward as you read the file and in the end it will reach the end of the file and once again you read , it wont return anything since there's nothing ahead of it. To know more about it, visit this link.
And these were the main problems due to which your code is not working correctly
There are also many more problems such as
Your way of reading from file
Your way of writing to the file
No error handling
Your way of closing the file
Your way of handling file
No encryptions
Security problems
Etc.
But for now, that's gonna help you in your task.
Good Luck And Smart Work!
Related
why am i unable to use list object syntax and am met with AttributeError: when running my program
i apologise for the longevity of this question I want to write a piece of code which essentially checks if the str name of an input has already been added within a txt file, let me tell you this scenario: I am using Classes and Listing in order to structure my data (stored in a txt file) for comparisons later, I am using the code that follows: import csv class Volunteer: def __init__(self,name,coin_type,weight_of_bag,true_count): self.name = name self.coin_type = coin_type #a function allowing me to class the data self.weight_of_bag = weight_of_bag self.TrueCount = true_count with open("CoinCount.txt","r+") as csvfile: #opens file as CSV *IMPORTANT* volunteers = [] for line in csvfile: volunteers.append(Volunteer(*line.strip().split(','))) I have also created some more simple code such as a menu etc, within this menu though I want to include the ability to input new volunteers, for now i havent actually gotten to the stage of appending new data to the txt file however, i am at the moment trying to create an inspection which checks if the inputted volunteers name has already been used before, just for more information, i will send the data within the txt file: Abena,5p,325.00,Y Malcolm,1p,3356.00,Y Jane,£2,120.00,Y Andy,£1,166.25,N Sandip,50p,160.00,Y Liz,20p,250.00,Y Andy,20p,250.00,Y Andy,50p,160.00,Y Jane,£1,183.75,N Liz,£,179.0,N Liz,50p,170.0,N Jane,50p,160.0,Y Sandip,£1,183.0,N Jane,£2,132.0,N Abena,1p,3356.0,N Andy,2p,250.0,N Abena,£1,175.0,Y Malcolm,50p,160.0,Y Malcolm,£2,175.0,N Malcolm,£1,175.0,Y Malcolm,1p,356.0,Y Liz,20p,250.0,Y Jane,£2,120.0,Y Jane,50p,160.0,Y Andy,£1,175.0,Y Abena,1p,359.56,N Andy,5p,328.5,N Andy,£2,108.0,N Malcolm,£2,12.0,N I will also give you the code for this part of the menu so that if you wish to explain to me how to fix it you will be able to use the same variable names def open_menu_1(): inputvolunteername = input("Enter the volunteers name you wish to add: ") if hasNumbers(inputvolunteername): yes_or_no = input("volunteer name contains numbers, would you like to try again? ") if yes_or_no == "yes" or "Yes": print("") open_menu_1() else: print("") print("you have been sent back to the main menu") print("") open_menu() elif any(not c.isalnum() for c in inputvolunteername): yes_or_no = input("volunteer name contains special characters, would you like try again? ") if yes_or_no == ("yes" or "Yes"): open_menu_1() else: print("") print("you have been sent back to the main menu") print("") elif inputvolunteername == volunteers[0].name: print("oi") I designed a tiny grain of the code i would need to test out if it would work,that is displayed at the bottom of the code above i essentially ran the program and typed in as the input the first name on the txt file (Abena) and by doing so, the console printed "oi". I thought this would be as difficult as this part of the code got as i thought all i would have to do now is replace elif inputvolunteername == volunteers[0].name: print("oi") with elif inputvolunteername == volunteers[0:].name: print("oi") i thought this would work because in lists this usually would go through all from 0 to infinity until there was nothing else to search from that name class category, however in actuality once i ran the program i was greeted with the following message: elif inputvolunteername == volunteers[0:].name: AttributeError: 'list' object has no attribute 'name' this confused me as I do have an attribute 'name' and that is made evident by the fact that that the other line of code which i tested out did work however by simply adding a colon it says that there is no attribute, please let me know what i need to change to the bottom line of code in order to make the program detect whether the inputvolunteername is equal to any of the names already written on the txt file.
There are duplicates in CSV... so to test for name in volunteer list of names I recommend using set() inputvolunteername in set([v.name for v in volunteers]) The following return True 'Abena' in set([v.name for v in volunteers])
Modifying code to default to option instead of asking user for selection?
I am not very experienced with python, just trying to make a modification to the code of a program I purchased. The code runs in the command terminal and its function is to gather data. It gives you the option of gathering the data in either csv or json. It prompts you once with asking which format and a second time for confirmation. Please enter output format (csv/json) Do you want to extract data in {} format? (y/n) I am trying to change this to just do csv by default, and not be prompted for either choosing or confirming I believe the relevant code from the program is the following ( this isn't all consecutive ). How do I alter the first part to just be 'csv' and do I need to do anything beyond deleting the entire def getConfirmMessage block to wipe that from the code? if spiderToExecute in range(1, 7): while True: outputFormat = click.prompt('Please enter output format (csv/json)', default='csv') outputFormat = ''.join(outputFormat).lower() if outputFormat in ['json', 'csv']: break settings.set('FEED_FORMAT', outputFormat) settings.set('FEED_URI', './data/{}.{}'.format(spiderConf['log_output_name_format'], outputFormat)) settings.set('LOG_FILE', './log/{}.log'.format(spiderConf['log_output_name_format'])) def getConfirmMessage(spiderToExecute, outputFormat): confirmMessages = { 1: 'Do you want to extract data from in {} format ?'.format(outputFormat), 2: 'Do you want to extract data from in {} format ?'.format(outputFormat), } return confirmMessages[spiderToExecute] edit: more code if not click.confirm(getConfirmMessage(spiderToExecute, outputFormat), default=True): click.echo() click.secho(' Please relaunch the command to select new options! ', bg='red') click.echo() raise click.Abort()
Complete steps (maybe): Remove the while loop and replace with outputFormat = "csv". You should be able to completely remove the code block you posted (if not click.confirm...). If that doesn't work, you'll need to post the code for click.confirm.
Python "In" Comparison with *$("!£*!'. characters
Seems while learning as I'm going with Python that I'm running into every little roadblock I can. Even though this is a simply "if" I can't seem to get it to work, and i was wondering if its because my input (pgName) has full stops within the string. e.g com.android.driver.software. In my example scenario, I will enter com.android.driver.software, what is listed within the Dict.value is com.android.driver.software.7 I thought using the comparison "in" would work in this instance, but it doesn't seem to be handling the logic at all.. What am i doing wrong? pgName = raw_input("Please enter a package name e.g com.android.driver.software: ") #while loop that checks user input from pgName to see if it matches any device #listed in the JSON output and if so printing all the entires for that value. while True: try: jdata = data["result"]["items"][y]["tagValues"]["IdDevicesMap"]["value"] for device in jdata.values(): if pgName in device: print jdata[device] print " " else: print 'false' When i run it everything is false.
Building a ranking list in Python: how to assign scores to contestants?
(I posted this on the wrong section of Stackexchange before, sorry) I'm working on a assignment which is way above my head. I've tried for days on end figuring out how to do this, but I just can't get it right... I have to make a ranking list in which I can enter a user, alter the users score, register if he/she payed and display all users in sequence of who has the most score. The first part I got to work with CSV, I've put only the basic part in here to save space. The menu and import csv have been done: (I had to translate a lot from my native language, sorry if there is a mistake, I know it's a bad habit). more = True while more: print("-" * 40) firstname = raw_input("What is the first name of the user?: ") with open("user.txt", "a") as scoreFile: scoreWrite = csv.writer(scoreFile) scoreWrite.writerow([firstname, "0", "no"]) scoreFile.close() mr_dnr = raw_input("Need to enter more people? If so, enter 'yes' \n") more = mr_dnr in "yes \n" This way I can enter the name. Now I need a second part (other option in the menu of course) to: let the user enter the name of the person after that enter the (new) score of that person. So it needs to alter the second value in any entry in the csv file ("0") to something the user enters without erasing the name already in the csv file. Is this even possible? A kind user suggested using SQlite3, but this basic CSV stuff is already stretching it far over my capabilities...
Your friend is right that SQlite3 would be a much better approach to this. If this is stretching your knowledge too far, I suggest having a directory called users and having one file per user. Use JSON (or pickle) to write the user information and overwrite the entire file each time you need to update it.
Code Stuck in a Loop and Need to Strip Characters from a File
I am trying to code a program that asks the user what the value of a variable is, opens a file, searches for a word, and then checks to see if the number after that word is equal to the user inputted variable, which means I have to get rid of the spaces in between that specific word and the number after it. Unfortunately, I am having some problems with my code and can’t figure out why it will not work. I am sorry if the question I am asking is fairly simple, I haven't coded in python in over a year and am extremely rusty to say the least. def getword1(prompt): while True: filestr1 = input(prompt) def getword2(prompt): while True: filestr2 = input(prompt) def getword3(prompt): while True: filestr3 = input(prompt) def openfile(prompt, missingfileerror): """Opens a file""" while True: try: filestr = input(prompt) return open(filestr) except FileNotFoundError: print(missingfileerror) uservariable1 = getword1("What is the value of the first variable? If not applicable, please enter 0") variable1search = ("Word1", uservariable1) uservariable2 = getword2("What is the value of the second variable? If not applicable, please enter 0") variable2search = ("Word2", uservariable2) uservariable3 = getword3("What is the value of the third variable? If not applicable, please enter 0") variable3search = ("Word3", uservariable3) file = openfile("Enter the name of the file that contains the variables.") if uservariable1 == ("0"): print("No uservariable1") else: if variable1search in file: print("The variable values match.") else: print("The variable values do not match.") if uservariable2 == ("0"): print("No uservariable2") else: if variable2search in file: print("The variable values match.") else: print("The variable values do not match.") if uservariable3 == ("0"): print("No uservariable3") else: if variable3search in file: print("The variable values match.") else: print("The variable values do not match.") file.close() When I run the code in terminal, the code asks my first question, but after I give it an answer, it is stuck in a loop of asking me the same first question over and over again. I also cannot remember how to properly use the .strip() function in this instance. I am searching for a string as my variable because the value of the variable will include a comma, such as 750,000 or 2,000. If I can strip the comma and also maybe a $ sign from the opened file, I would be able to search for an int instead of a string. Thanks for your time!
Remove the while loop from the openfile function. It has no use. def openfile(prompt, missingfileerror): """Opens a file""" try: filestr = input(prompt) return open(filestr) except FileNotFoundError: print(missingfileerror) NB. One other slight problem with your setup is that you should always close files that you've opened. But in this function, you cannot do that anymore, because the code after return will not be executed (if there are no errors). Another problem is that your code is not DRY (look up the principle). You've duplicated many functions that are almost identical. There is probably a way to do this in 1/3 of the code. Another problem is that you have added while loops in getword<x> as well, they are not needed either.
To answer your first point, the code is getting stuck asking the first question repeatedly because of your while True in getword1(). There is an also an awful lot wrong with the rest of your code: Unnecessary while loops everywhere You don't return anything from your getword() functions, (so uservariable1 etc. will end up as None) You don't need 3 separate getword() functions, one would do Actually, you don't really need any, (if you're not going to do any validation), you could just write uservariable1 = input("What is the value ...") etc. if variable2search in file will never return True - you need to iterate over the file's contents If you do want to do some user input validation, you could try something like: def getword(prompt): while True: foo = input(prompt) if <some evaluation criteron here>: return foo #Return input and break out of while loop I suggest reading up on while and file access, as a minimum. Finally, try writing your code in small chunks and proving each bit works before moving on to the next, it's easier to debug that way.