So I'm making a text-only password manager purely in python and I have a function that simply writes to a file. It checks which file it's writing to and writes the data accordingly. The only difference really is the lack of a newline character at the end. Now, whenever the second write method is called in the elif statement, it creates the file, doesn't generate any errors so the program continues, but the file itself is empty.
def write_to_file(file, data, function):
x = input("Y/N: ").lower()
if x == "y":
with open(f"{path}\\{file}", mode = "a", encoding = "utf-8") as f:
if file == "passwords.dat":
f.write(f"{data}\n")
print("The password has been saved!")
retry(function)
if file == "master_password.dat":
f.write(data)
print("The master password has been saved! You will be redirected to the menu shortly.")
sleep(1)
main_menu()
Related
I am making a small simple password manager in python. I have the functions of creating an account which has 3 inputs, Username, Password, and Website. I have a function to view all the accounts which shows the contents of the file info.txt where all that information goes. Im trying to create a function to delete an entry but im not sure how to make the function delete all the lines of information associated with the Username. I want an input asking "Which account to delete" you put the username, and it will delete all information associated with the username in info.txt
Code:
import os.path #Imports os module using path for file access
def checkExistence(): #Checking for existence of file
if os.path.exists("info.txt"):
pass #pass is used as a placeholder bc if no code is ran in an if statement and error comes.
else:
file = open("info.txt", "w") #creates file with name of info.txt and W for write access
file.close()
def appendNew():
#This function will append a new password in the txt file
file = open("info.txt", "a") #Open info.txt use a for appending IMPORTANT: opening a file with w for write will write over all existing data
userName = input("Enter username: ")
print(userName)
os.system('cls')
password = input("Enter password: ")
print(password)
os.system('cls')
website = input("Enter website: ")
print(website)
os.system('cls')
print()
print()
usrnm = "Username: " + userName + "\n" #Makes the variable usrnm have a value of "Username: {our username}" and a new line
pwd = "Password: " + password + "\n"
web = "Website: " + website + "\n"
file.write("----------------------------------\n")
file.write(usrnm)
file.write(pwd)
file.write(web)
file.write("----------------------------------\n")
file.write("\n")
file.close()
def readPasswords():
file = open("info.txt", "r") #Open info.txt with r for read
content = file.read() # Content is everything read from file variable (info.txt)
file.close()
print(content)
checkExistence()
while True:
choice = input("Do you want to: \n 1. Add account\n 2. View accounts\n 3. Delete account\n")
print(choice)
if choice == "1":
os.system('cls')
appendNew()
elif choice == "2":
os.system('cls')
readPasswords()
elif choice == "3":
os.system('cls')
else:
os.system('cls')
print("huh? thats not an input.. Try again.\n")
I tried making a delete account function by deleting the line which matched the username. My only problem is that it only deletes the line in info.txt with the username, but not the password and website associated with that username.
Firstly, you're using the wrong tool for the problem. A good library to try is pandas, using .csv files (which one can think of as pore program oriented excel files). However, if you really want to use the text file based approach, your solution would look something like this:
with open(textfile, 'r+') as f:
lines = [line.replace('\n', '') for line in f.readlines()]
# The above makes a list of all lines in the file without \n char
index = lines.index(username)
# Find index of username in these lines
for i in range(5):
lines.pop(index)
# Delete the next five lines - check your 'appendNew' function
# you're using five lines to write each user's data
print(lines)
f.write("\n".join(lines))
# Finally, write the lines back with the '\n' char we removed in line 2
# Here is your readymade function:
def removeName(username):
with open("info.txt", 'r+') as f:
lines = [line.replace('\n', '') for line in f.readlines()]
try:
index = lines.index(username)
except ValueError:
print("Username not in file!")
return
for i in range(5):
lines.pop(index)
print(lines)
f.write("\n".join(lines))
# Function that also asks for username by itself
def removeName_2():
username = input("Enter username to remove:\t")
with open("info.txt", 'r+') as f:
lines = [line.replace('\n', '') for line in f.readlines()]
try:
index = lines.index(username)
except ValueError:
print("Username not in file!")
return
for i in range(5):
lines.pop(index)
print(lines)
f.write("\n".join(lines))
# Usage:
removeName(some_username_variable)
removeName_2()
Again, this is a rather clunky and error prone approach. If you ever change the format in which each user's details are stored, your would have to change the number of lines deleted in the for loop. Try pandas and csv files, they save a lot of time.
If you're uncomfortable with those or you're just starting to code, try the json library and .json files - at a high level they're simple ways of storing data into files and they can be parsed with the json library in a single line of code. You should be able to find plenty of advice online about pandas and json.
If you're unable to follow what the function does, try reading up on try-except blocks and function parameters (as well as maybe global variables).
The entire program works fine if I have one username in the users.csv file, but as soon as a second is added repl (IDE) quits the program. I know the code is very messy and amateur but for now I'm just looking to fix this part.
Part that needs to be altered v
def login():
existing = input("Do you already have a account? Y/N >" ).upper()
if existing == "Y":
pass
else:
print("Welcome to the regristration page")
file = open("users.csv", "a+")
file.write("{}\n".format(input("What would you like your username to be? >")))
file.close()
login()
def auth_users():
username = input("What is your username?")
file = open("users.csv","r")
reader = csv.reader(file)
for record in reader:
if record[0] == username:
continue
else:
exit()
file.close()
auth_users()
Program in its entirety
def login():
existing = input("Do you already have a account? Y/N >" ).upper()
if existing == "Y":
pass
else:
print("Welcome to the regristration page")
file = open("users.csv", "a+")
file.write("{}\n".format(input("What would you like your username to be? >")))
file.close()
login()
def auth_users():
username = input("What is your username?")
file = open("users.csv","r")
reader = csv.reader(file)
for record in reader:
if record[0] == username:
continue
else:
exit()
file.close()
auth_users()
There is no error while running your program. Either way, no matter if the user exists in your file or not, your program will end without output.
You can try to improve things a bit:
def auth_users():
username = input("What is your username?")
file = open("users.csv","r")
reader = csv.reader(file)
for record in reader:
if record[0] == username:
print(f"Hello, {username}")
exit() # You found the guy, exit your program here
# Don't exit here: go through all the names until you find the guy (or not)
# End of the loop. We didn't find the guy.
print("You're not registered")
Here is the problem
for record in reader:
if record[0] == username:
continue
else:
exit()
You are probably mistaken in your use of exit() and continue. The exit function is usually called when you want to exit out of python's interactive mode and raises the SystemExit exception (in this case causing your program to exit). continue on the other hand tells python to move on to the next step in the loop.
You probably want to do something like this instead:
for record in reader:
if record[0] == username:
# Handle authenticated users here
print("Login successful")
return # exit the function
# Handle unauthenticated users here
print("User not found")
You should also consider replacing your file opening and closing with context managers. Instead of:
my_file = open("some-file", "r")
# read some input from the file
my_file.close()
# ...
my_file = open("some-file", "w")
# write some output to the file
my_file.close()
use:
with open("some-file", "r") as my_file:
# read my_file in here
# ...
with open("some-file", "w") as my_file:
# write to my_file in here
This way python tries to close your file even if an exception is encountered along the way.
I have the following code:
print "We're going to write to a file you'll be prompted for"
targetfile = raw_input('Enter a filename: ')
targetfilefound = open('targetfile' , 'w')
print "What do we write in this file?"
targetfilefound.write("hello this is working!")
targetfilefound.close()
The script I'm creating should be able to write to a file that the user defines via raw_input. The above could be faulty at core, open to suggestions.
Judging by the stuff the script is printing you probably want the user to input what should be printed to the file so:
print "We're going to write to a file you'll be prompted for"
targetfile = raw_input('Enter a filename: ')
targetfilefound = open(targetfile , 'w')
print "What do we write in this file?"
targetfilefound.write(raw_input())
targetfilefound.close()
Note: This method will create the new file if it does not exist. If you want to check whether the file exists you can use the os module, something like this:
import os
print "We're going to write to a file you'll be prompted for"
targetfile = raw_input('Enter a filename: ')
if os.path.isfile(targetfile) == True:
targetfilefound = open(targetfile , 'w')
print "What do we write in this file?"
targetfilefound.write(raw_input())
targetfilefound.close()
else:
print "File does not exist, do you want to create it? (Y/n)"
action = raw_input('> ')
if action == 'Y' or action == 'y':
targetfilefound = open(targetfile , 'w')
print "What do we write in this file?"
targetfilefound.write(raw_input())
targetfilefound.close()
else:
print "No action taken"
As pointed out by others, remove the quotes from target file as you have assigned it already to a variable.
But actually instead of writing as code you can use the with open as given below
with open('somefile.txt', 'a') as the_file:
the_file.write('hello this is working!\n')
In the above case, you don't need to do any exception handling while processing the file. When-ever an error occurs the file cursor object is automatically closed and we dont need to explicitly close it. Even it writing to file it success, it will automatically close the file pointer reference.
Explanation of efficient use of with from Pershing Programming blog
Okay so I'm trying to write a script that takes two files and modifies the first before writing it into the destination fine, but whenever I run it, the script only prints the first modified line over and over again.
#3a
def modify(string):
"""Takes a string and returns a modified version of the string using two modifications. One must be a replacement of some kind.
string -> string"""
while string != "":
string = string.upper()
string = string.replace("A","4").replace("B","8").replace("C","<").replace("E","3").replace("G","6").replace("I","1").replace("O","0").replace("R","|2").replace("S","5").replace("T","7").replace("Z","2")
print(string)
#3b - asks the user to type in a source code filename and destination filename; opens the files; loops through the contents of the source file line-by-line, using modify() to modify eat line before writing it to the destination file; the closes both files.
source = input("What file would you like to use?")
destination = input("Where would you like it to go?")
filesource = ""
while filesource == "":
try:
file_source = open(source, "r")
file_destination = open(destination, "w")
for item in file_source:
mod = modify(item)
file_destination.write(mod)
file_source.close()
file_destination.close()
break
except IOError:
source = input("I'm sorry, something went wrong. Give me the source file again please?")
Any help?
Hint: if you run modify("TEST ME") what does it return?
add return string to the end of the modify function.
The string never empties - try parsing through it char by char using an index int and your conditional being while i < len(string)
I have written two scripts Write.py and Read.py.
Write.py opens friends.txt in append mode and takes input for name, email ,phone no and then dumps the dictionary into the file using pickle.dump() method and every thing works fine in this script.
Read.py opens friends.txt in read mode and then loads the contents into dictionary using pickle.load() method and displays the contents of dictionary.
The main problem is in Read.py script, it justs shows the old data, it never shows the appended data ?
Write.py
#!/usr/bin/python
import pickle
ans = "y"
friends={}
file = open("friends.txt", "a")
while ans == "y":
name = raw_input("Enter name : ")
email = raw_input("Enter email : ")
phone = raw_input("Enter Phone no : ")
friends[name] = {"Name": name, "Email": email, "Phone": phone}
ans = raw_input("Do you want to add another record (y/n) ? :")
pickle.dump(friends, file)
file.close()
Read.py
#!/usr/bin/py
import pickle
file = open("friends.txt", "r")
friend = pickle.load(file)
file.close()
for person in friend:
print friend[person]["Name"], "\t", friend[person]["Email"] , "\t", friend[person]["Phone"]
What must be the problem, the code looks fine. Can some one point me in the right direction ?
Thanks.
You have to load from the file several times. Each writing process ignores the others, so it creates a solid block of data independent from the others in the file. If you read it afterwards, it reads only one block at a time. So you could try:
import pickle
friend = {}
with open('friends.txt') as f:
while 1:
try:
friend.update(pickle.load(f))
except EOFError:
break # no more data in the file
for person in friend.values():
print '{Name}\t{Email}\t{Phone}'.format(**person)
You have to call pickle.load once for each time you called pickle.dump. You write routine does not add an entry to the dictionary, it adds another dictionary. You will have to call pickle.load until the entire file is read, but this will give you several dictionaries you would have to merge. The easier way for this would be just to store the values in CSV-format. This is as simple as
with open("friends.txt", "a") as file:
file.write("{0},{1},{2}\n".format(name, email, phone))
To load the values into a dictionary you would do:
with open("friends.txt", "a") as file:
friends = dict((name, (name, email, phone)) for line in file for name, email, phone in line.split(","))