I'm trying to create a username database and the code all runs how I want except for when I try to test if the file contains the entered text. For some reason it just runs past the elif statement and hits the else statement if it already exists in the text.
Here is the full code:
class username:
def add():
while(True):
file = open("usernames.txt", 'r+')
names = list(file.read())
entered = str(input("Username: "))
if len(entered) == 0:
print("Please enter a valid username\n")
continue
elif not(entered.isalpha):
print("Please enter a valid username\n")
continue
elif entered in file.read():
print("That name is already in use.",
"\nPlease enter a different username. \n")
continue
elif len(entered) < 4 or len(entered) > 12:
print("Please enter a username with 4-12 characters.\n")
continue
else:
print(entered)
file.close()
add = open("usernames.txt", 'a+')
plusnewline = entered + "\n"
add.write(plusnewline)
add.close()
break
def list():
file = open("usernames.txt","r+")
names = file.read()
print(names)
file.close()
username.add()
username.list()
edit: Answered by Shadow:
Changed:
names = list(file.read())
to:
names = file.read()
and changed:
elif entered in file.read():
to:
elif entered in names:
You can only call file.read once - after that it's already read.
Either use file.seek(0) to go back to the start of the file (which will allow you to read it again), or cache the contents in a variable so that you can reuse it (that is, refer to your names variable)
Related
I'm trying to get my code to check if a word is already in the document. However when choosing a variable (username) that happens to share the same letters going to the right as the preexisting one in the file, it thinks that the name is taken. For example, if abcdefg was in the file, if I was to right defg or fg or g, it would think the username was taken.
def register():
print("━━━━ACCOUNT CREATION━━━━")
username = input("Create Username: ")
with open("Login.txt", "r") as loginfile:
if (username+",") in loginfile.read():
print("Sorry, but that username is taken.")
choice = input("Try again with a new name? (Y/N)")
choice = choice.upper()
My case:
Say I had the name, Joe which is already in the file. If I tried to make a username that is just e, then it would think it is Joe, as it is looking for the e, next to a comma.
Anyway to fix this? Thanks!
This should work
with open('login.txt', 'r') as LoginFile:
# the split function splits a string to a list on mark
Data = LoginFile.read().split(" ,")
if username in Data:
# .....
if this isn't what you want try this built-in module :
https://docs.python.org/3/library/re.html
def register():
print("━━━━ACCOUNT CREATION━━━━")
# read the names from the file
with open('Login.txt', 'r') as f:
names = f.read().split(',')
username = input("Create Username: ")
for name in names:
# check if any names end with this name have been created
if name.endswith(username):
# found
print("Sorry, but that username is taken.")
# we want to keep ask the user to select if
# they enter something other than Y/N
while True:
# ask for the option
option = input("Try again with a new name? (Y/N) ")
# try again, we just rerun this function
if option == 'Y':
register()
# don't ask any more
break
elif option == 'N':
# exit if user chooses N
break
# if the user chooses something else, continue
# the loop and keep asking
# if no names end with username, goto else
break
else:
# name available, save it to the file
print("Name created successfully:", username)
new_names = names + [username]
with open('Login.txt', 'w') as f:
f.write(','.join(new_names))
I have tested it, please try and see if it works for you.
There's one last feature I want for my bank account system.
I want it to check if a username has already been saved to the text file database. If the username already exists, then it should tell the user that they can't have that name option. If not, then they would be able to use it.
The rest of my code works as it should, it's just the fcat that I can't append/update my text file properly and see if usernames already exist in the text file database.
import sys
users = {}
status = ""
# Functions ---------------------------------------------------------------------------------------------------------
# Select either account creation or login
def displayMenu():
global status
status = input("Are you a registered user? \n1 - Yes \n2 - No \nQ - Quit \n")
if status == '1':
oldUser()
elif status == '2':
newUser()
else:
print("Unknown input error, exiting . . . .")
sys.exit(0)
return status
# Account creation
def newUser():
global createLogin
createLogin = input("Create login name: ")
if createLogin in users: # check if login name exists
print ("\nLogin name already exists!\n")
else:
createPassw = input("Create password: ")
users[createLogin] = createPassw # add login and password
print("\nAccount created!\n")
#---- Storing the username in a txt file
file = open("accountfile.txt", "a")
file.write(createLogin)
file.write("\n")
file.close()
oldUser()
# Account login
def oldUser():
global login
login = input("Enter login name: ")
passw = input("Enter password: ")
# check if user exists and login matches password
if login in users and users[login] == passw:
file = open("accountfile.txt", "r")
for text in file: ######## This is where I'm trying to compare username duplicates
if text in file == createLogin:
print("Username already exists!")
print("\nLogin successful!\n")
Bank_Account()
else:
print("\nUser doesn't exist or wrong password!\n")
print("Restarting. Please enter details correctly . . . . .")
sys.exit(0)
class Bank_Account:
def __init__(self):
self.balance=0
response = ''
def deposit(self):
try:
amount=float(input("Enter amount to be Deposited: "))
except ValueError:
print("Enter digits only")
else:
self.balance += amount
print("\n Amount Deposited:",amount)
def withdraw(self):
try:
amount = float(input("Enter amount to be Withdrawn: "))
if self.balance>=amount:
self.balance-=amount
print("\n You Withdrew:", amount)
except ValueError:
print("Enter digits only")
s.withdraw()
else:
print("\n ")
def display(self):
print("\n Remaining Balance=",self.balance)
displayMenu()
s = Bank_Account()
# Calling functions with that class object
s.deposit()
s.withdraw()
s.display()
So it looks you are are writing the user input in the file accountfile.txt. So after a few users log in it might look something like:
$ cat accountfile.txt
mike
sarah
morgan
lee
The section of your code in question is here:
file = open("accountfile.txt", "r")
for text in file:
if text in file == createLogin:
print("Username already exists!")
This particular part is probably not doing what you think it's doing:
if text in file == createLogin
...
if text in file is returning either True or False.
...
So the line above is essentially saying
if False == createLogin
or
if True == createLogin
I believe what you want to do is check if a name is in accountfile.txt. The smallest change you could make to your code in order to achieve that would be
file = open("accountfile.txt", "r")
for text in file:
if text.strip() == createLogin: # .strip() will clean up the \n
print("Username already exists!")
This line:
if text in file == createLogin: is where you are making a mistake. The line is essentially saying:
"(if the text is in the file) compare the result of that check with the string createLogin".
i.e. if (True/False) == createLogin, which is always false because the True/False boolean primitives are never equal to any string (if it actually runs, i have not tested to see if an exception will be thrown).
what you should do is this
for text in file: # get one line of text
if createLogin == text.strip(): # compare the line with the user input string
print("Username already exists!")
break
.strip() removes any leading or trailing spaces in the database stored name (in this case the line break character \n used to denote the end of a line in the file. break ends the loop prematurely cos your lookup is complete since you found what you were looking for, and it would be an unnecessary to continue comparing the user input with other strings, imagine the txt had 1000 names and the 1st name was a match, the user would see the error printed but the program would continue running for the rest of the 999 tries, making it seem sluggish and waste unnecessary CPU cycles.
The database is still case sensitive however which may or may not be desired depending on your requirements. For case insensitivity you could do the following:
for text in file: # get one line of text
if createLogin.lower() == text.strip().lower(): # compare the line with the user input string
print("Username already exists!")
break
.lower() makes both strings into lower case strings and then checks if they are the same, eliminating the case sensitivity.
Instead of writing to the text file, try pickling the database.
This will save a representation of the object that you can easily load back into your program.
import pickle
users = {}
users["Ash"] = "password"
pickle.dump(users, open("users.p", "wb"))
loaded_users = pickle.load(open("users.p", "rb"))
print(loaded_users)
A more advanced solution may also be to check out a relational database, such as [sqlite3][1]
I have a try/except block in a function that asks the user to enter the name of a text file to open. If the file does not exist, I want the program to ask the user for the filename again either until it is located or the user hits ENTER.
Right now the try/except block just runs infinitely.
def getFiles(cryptSelection):
# Function Variable Definitions
inputFile = input("\nEnter the file to " + cryptSelection +\
". Press Enter alone to abort: ")
while True:
if inputFile != '':
try:
fileText = open(inputFile, "r")
fileText.close()
except IOError:
print("Error - that file does not exist. Try again.")
elif inputFile == '':
input("\nRun complete. Press the Enter key to exit.")
else:
print("\nError - Invalid option. Please select again.")
return inputFile
You need to break out of the while loop, this has to be done at 2 places:
After reading the file (when it is a correct file)
After the Enter key is pressed. because we want to end.
Also you need to prompt the question inside the loop so the question is asked again at every iteration and the inputFile value is updated with the latest user input
One last thing, I think your else clause can be removed as it is never accessed, the if and elif catch all the possibilities (ie, inputFile has a value or not).
def getFiles(cryptSelection):
while True:
inputFile = input("\nEnter the file to %s. Press Enter alone to abort:" % cryptSelection)
if inputFile != '':
try:
fileText = open(inputFile, "r")
fileText.close()
# break out of the loop as we have a correct file
break
except IOError:
print("Error - that file does not exist. Try again.")
else: # This is the Enter key pressed event
break
return inputFile
you have a while True but no break in your code you probably want to break after the fileText.close() like this:
try:
fileText = open(inputFile, "r")
fileText.close()
break
except IOError:
print("Error - that file does not exist. Try again.")
but really you should change this check to use os.path.isfile like this:
import os
def getFiles(cryptSelection):
inputFile = input("\nEnter the file to " + cryptSelection +\
". Press Enter alone to abort: ")
while True:
if inputFile != '':
if os.path.isfile(inputFile):
return inputFile
else:
print("Error - that file does not exist. Try again.")
elif inputFile == '':
input("\nRun complete. Press the Enter key to exit.")
else:
print("\nError - Invalid option. Please select again.")
That is because you don't assign a new value to inputFile within the while loop.
It will hold the same value forever...
EDIT
Once you will assign a new value to inputFile within the loop - make sure to break out when the exit condition is met ("user hits Enter")
I am trying to create a registrar system through Python with pickles. I have gotten the system to record user input, but it does not save it for future implementations of the program.
Here is the code that will start the program:
import datetime
import pandas as pd
import pickle as pck
import pathlib
from pathlib import *
from registrar import *
prompt = "Please select an option: \n 1 Create a new course \n 2 Schedule a new course offering \n 3 List this school's course catalogue \n 4 List this school's course schedule \n 5 Hire an instructor \n 6 Assign an instructor to a course \n 7 Enroll a student \n 8 Register a student for a course \n 9 List this school's enrolled students \n 10 List the students that are registered for a course \n 11 Submit a student's grade \n 12 Get student records \n 13 Exit"
farewell = "Thank you for using the Universal University Registrar System. Goodbye!"
print ("Welcome to the Universal University Registration System.")
print ("\n")
try: #As long as CTRL-C has not been pressed, or 13 not been input by user.
input_invalid = True
while input_invalid:
inst = input("Please enter the name of your institution. ").strip()
domain = input("Please enter the domain. ").strip().lower()
if inst == "" or domain == "":
print("Your entry is invalid. Try again.")
else:
input_invalid = False
schoolie = Institution(inst, domain)
if Path(inst + '.pkl').exists() == False:
with open(inst + '.pkl', 'r+b') as iptschool:
schoolie = pck.load(iptschool)
while True:
print (prompt)
user_input = input("Please enter your choice: ")
try:
user_input = int(user_input)
if user_input < 1 or user_input > 14: #UserInput 14: on prompt.
raise ValueError("Please enter a number between 1 and 13, as indicated in the menu.")
except ValueError:
print("Not a valid number. Please try again.")
if user_input == 1: #Create a new course
input_invalid2 = True #Ensure that the user actually provides the input.
while input_invalid2:
input_name = input("Please enter a course name: ").strip()
input_department = input("Please enter the course's department: ").strip()
input_number = input("Please enter the course's number (just the number, not the departmental prefix): ").strip()
try:
input_number = int(input_number)
except ValueError:
print ("Please print an integer. Try again.")
input_credits = input("Please enter the number of credits awarded for passing this course. Please use an integer: ").strip()
try:
input_credits = int(input_credits)
except ValueError:
print ("Please print an integer. Try again.")
if input_name != "" and input_department != "" and input_number and input_credits:
input_invalid2 = False #Valid input
else:
print("One or more of your entries is invalid. Try again.")
added_course = Course(input_name, input_department, input_number, input_credits)
for course in schoolie.course_catalog:
if course.department == input_department and course.number == input_number and course.name == input_name:
print("That course is already in the system. Try again.")
input_invalid2 == True
if input_invalid2 == False:
schoolie.add_course(added_course)
print ("You have added course %s %s: %s, worth %d credits."%(input_department,input_number,input_name, input_credits))
And here is the second option, which SHOULD reveal that it is stored, but it does not.
elif user_input == 2: #Schedule a course offering
input_invalid2 = True #Ensure that the user actually provides the input.
while input_invalid2:
input_department = input("Please input the course's department: ").strip()
input_number = input("Please input the course's number: ").strip()
course = None
courseFound = False
for c in schoolie.course_catalog:
if c.department == input_department and c.number == input_number: #Course found in records
courseFound = True
course = c
input_section_number = input("Please enter a section number for this course offering: ").strip()
input_instructor = input("If you would like, please enter an instructor for this course offering: ").strip()
input_year = input("Please enter a year for this course offering: ").strip()
input_quarter = input("Please enter the quarter in which this course offering will be held - either SPRING, SUMMER, FALL, or WINTER: ").strip().upper()
if input_course != "" and input_course in schoolie.course_catalog and input_section_number.isdigit() and input_year.isdigit() and input_quarter in ['SPRING', 'SUMMER', 'FALL', 'WINTER'] and input_credits.isdigit():
if input_instructor != "": #Instructor to be added later, if user chooses option 6.
added_course_offering = CourseOffering(c, input_section_number, None, input_year, input_quarter)
else:
added_course_offering = CourseOffering(c, input_section_number, input_instructor, input_year, input_quarter)
schoolie.add_course_offering(added_course_offering)
input_invalid2 = False #Valid input
print ("You have added course %s, Section %d: %s, worth %d credits."%(input_course,input_section_number,input_name, input_credits))
else:
print("One or more of your entries is invalid. Try again.")
if courseFound == False: #If course has not been found at the end of the loop:
print("The course is not in our system. Please create it before you add an offering.")
break
By the way, I think I have the system closing properly. Correct me if I'm wrong:
elif user_input == 13: #Exit
with open(inst + '.pkl', 'wb') as output:
pck.dump(schoolie, output, pck.HIGHEST_PROTOCOL)
del schoolie
print (farewell)
sys.exit()
except KeyboardInterrupt: #user pushes Ctrl-C to end the program
print(farewell)
I believe that there is something wrong with the way that I am setting up the pickles files. I'm creating them, but I seem not to be putting data into them.
I apologize for the long-winded nature of this question, but I hope that the details will help you understand the problems that I've been having. Thanks in advance for the help!
it seems you may have dump and load reversed: (from the docs)
Signature: pck.load(file, *, fix_imports=True, encoding='ASCII', errors='strict')
Docstring:
Read and return an object from the pickle data stored in a file.
Signature: pck.dump(obj, file, protocol=None, *, fix_imports=True)
Docstring:
Write a pickled representation of obj to the open file object file.
With all those lines of code, it does get a little confusing, but I don't see any code that is pickling and writing the objects to a file.
Before anything else, you should assign the file to a variable so you can reference it. To do this, you'll have code similar to this:MyFile = open("FileName.extension","wb"). MyFile can be any name you want, it will be what you use later to reference the file. FileName is the name of the file itself. This is the name it will have in File Explorer. .extension is the file's extension, specifying the type of file. You should use .dat for this. wb is the file access mode. "w" means write, and "b" means binary. (Pickled objects can only be stored in a binary file.)
To write the pickled objects, you'll need this code:pck.dump(object,MyFile). (Usually, you would use pickle.dump(object,MyFile), but you imported pickle as pck.)
After writing the data to the file, you'll want to retrieve it. To do this, the "wb" instance of MyFile needs to be closed like this:MyFile.close(). Then you'll need to re-open the file in read mode using the following code:MyFile = open("FileName.extension","rb") Then you would use this:object = pickle.load(MyFile) to read the data. In the preceding example, (the load function), your object must have the same name as when you pickled it using the dump function. (pck.dump(object,MyFile))
In the end, you'll end up with something similar to this:
if writing conditions are true:
MyFile = open("FileName.dat","wb")
pickle.dump(object,MyFile) # This will be repeated for each object.
MyFile.close()
if reading conditions are true:
MyFile = open("FileName.dat","rb")
object = pickle.load(MyFile) # This will be repeated for each object.
MyFile.close()
I'm sorry if this wasn't the answer you wanted. Because of all those lines of code, it is somewhat hard to understand. I need clarification to give a better answer.
I am currently trying to make a program where the user can create sets of data, but I am having a difficult time figuring out how to handle the user picking the user picking a name out of a list of files to edit or view.
Here is how I display the files they can choose from. How can I easily allow them to choose any one of the available files without hardcoding each individual one?
available_files = os.listdir('./DSC_Saves/')
print(available_files)
user_input = input('File Name: ')
What I would like to avoid doing is the following:
if user_input == available_files[0]:
#do action
elif user_input == available_files[1]:
#do action 2
elif user_input == available_files[2]:
#do action 3
As mentioned, you can do this by using in on the list of available files as follows:
available_files = os.listdir('./DSC_Saves/')
print(available_files)
while True:
user_input = input('File name: ')
if user_input in available_files:
break
print("You have selected '{}'".format(user_input))
Alternatively, to make it easier to type, you could present the user with a numeric menu to choose from as follows:
available_files = os.listdir('./DSC_Saves/')
for index, file_name in enumerate(available_files, start=1):
print('{:2} {}'.format(index, file_name))
while True:
try:
user_input = int(input('Please select a file number: '))
if 1 <= user_input <= len(available_files):
selected_file = available_files[user_input-1]
break
except ValueError as e:
pass
print("You have selected '{}'".format(selected_file))
Both solutions will continue prompting until a valid file name has been entered.
So for example you could see the following output:
1 test1.txt
2 test2.txt
Please select a file number: 3
Please select a file number: 2
You have selected 'test2.txt'