comparing user input to text file - python

from pip._vendor.distlib.compat import raw_input
class Login:
def logging_in(self):
StudentID = raw_input("please enter your student id. ")
f = open("StudentDetails.txt", "r+")
lines = f.readlines()
if StudentID == lines:
print("Verified Welcome")
else:
print("you are not a registered Student Goodbye")
f.close()
login = Login()
login.logging_in()
I'm atempting to compare my user input to my variables inside the text file. Every time I atempt to type in a student id (0001,0002) It keeps Printing the you are not a registered student goodbye. How to resolve this?

You can load the valid IDs once when the instance is created. Then when a user tries to login, you just check if the ID exists in that set. For example:
from pip._vendor.distlib.compat import raw_input
class Login:
def __init__(self):
with open("StudentDetails.txt", 'r') as file:
lines = file.readlines()
self.valid_ids = set([s.strip() for s in lines])
def logging_in(self):
StudentID = raw_input("please enter your student id. ")
if StudentID.strip() in self.valid_ids:
print("Verified Welcome")
else:
print("you are not a registered Student Goodbye")
login = Login()
login.logging_in()

You're comparing input ID against a list, you need add a for loop
def logging_in(self):
StudentID = raw_input("please enter your student id. ")
f = open("StudentDetails.txt", "r+")
lines = f.readlines()
for line in lines
if StudentID in line:
print("Verified Welcome")
else:
print("you are not a registered Student Goodbye")
f.close()
BTW, as #Cohan says in comments, any character in line will give access to user. I am assuming this is just for learning purposes, and not a real security approach.

Related

Use values from another function python3

I have this code, but i dont know how to use the "age" from the user in the other function any clue what i have wrong?
def accounts():
yourCode = input("Please enter your user code. \nIf you already have an account, type your account user code. \nOtherwise, enter a new one to create an account: ")
with open("users.txt", "r") as rf:
users = rf.readlines()
for each_user in [user.split(",") for user in users]:
if each_user[0] == yourCode:
print(f"Welcome {each_user[1]}")
age = each_user[2]
xxApp()
return None
with open("users.txt", "a") as af:
name = input("Please enter your name: ")
age = input("Enter your age: ")
af.write(f"{yourCode},{name},{age}\n")
print(f"Thank you {name}, your information has been added.")
xxApp()
def xxApp():
age = each_user[2]
print(age)
Pass it as a parameter
def accounts():
yourCode = input("Please enter your user code. \nIf you already have an account, type your account user code. \nOtherwise, enter a new one to create an account: ")
with open("users.txt", "r") as rf:
users = rf.readlines()
for each_user in [user.split(",") for user in users]:
if each_user[0] == yourCode:
print(f"Welcome {each_user[1]}")
xxApp(each_user)
return None
...
def xxApp(user):
age = user[2]
print(age)
You're defining age = each_user[2], but the each_user variable is only available in the scope of accounts().
You can read about python scopes here
I would modify the xxApp() function to take in a variable as a parameter like this
def xxApp(each_user):
age = each_user[2]
print(age)
then you call xxApp() with the each_user passed as a parameter, so it is available inside the scope of xxApp(), like this xxApp(each_user)

Update single field in text file python

I have this function:
def favourites():
name = input("Enter your name as you did when you signed up: ")
new_artist = input("Would you like to edit your favourite artist? y/n ").lower().strip()
if new_artist == 'yes' or new_artist == 'y':
old_artist = input("Enter the favourite artist you used when signing up: ")
artist = input("Enter your new favourite artist: ")
usersFile = open('users.txt', 'r+')
usersRec = usersFile.readline()
# reads each line in the file
while usersRec != "":
# splits each record into fields
field = usersRec.split(',')
if field[0] == name:
usersFile.write(field[2].replace(old_artist, artist))
usersRec = usersFile.readline()
usersFile.close()
I have read a line in the text file and then split it into fields and i want to update a single field. Searched and found the update() function so tried that but it doesn't work and i'm not sure what i'm doing wrong. Any suggestions?
You should write to file in another stream, opening file for writing. Also made some corrections in readlines() method and 'replace' part (you should put the result into variable which is field[2]):
import io
import sys
def favourites():
content=[]
name = input("Enter your name as you did when you signed up: ")
new_artist = input("Would you like to edit your favourite artist? y/n
").lower().strip()
if new_artist == 'yes' or new_artist == 'y':
old_artist = input("Enter the favourite artist you used when signing
up: ")
artist = input("Enter your new favourite artist: ")
with open('users.txt', 'r+') as usersFile:
usersRec = usersFile.readlines()
print(usersRec)
# reads each line in the file
for ur in usersRec:
# splits each record into fields
field = ur.split(',')
if field[0] == name:
field[2] = field[2].replace(old_artist, artist)
content.append(','.join(field))
else:
content.append(','.join(field))
usersRec = usersFile.readline()
usersFile.close()
writeToFile(content)
def writeToFile(content):
with open('users.txt', 'w+') as usersFile:
for line in content:
usersFile.write(line)
usersFile.close()
if __name__=="__main__":
favourites()

Login program from external text file

I'm having issues with a code where I have to get a user to type details about themselves, which saves to a text file. When the user tries to log in, it will check the text file for their details. Here is my code below. It works at first, where the user is granted access, but whenever I do a restart to my computer, or Python itself, it only grants the last user access. Some help would be appreciated, thank you:
This is what it looks like in the text file:
Adam16,adam123,Adam,Sunderland,16
Johnny18,johnny150,Johnny,Vane,18
This is the source code:
import csv
import sys
def register():
firstname = input("First name: ")
surname = input("Surname: ")
age = int(input("Age: "))
password = input("Password: ")
username = firstname[:3] + str(age)
with open("account.txt","a",newline="") as myfile:
writer = csv.writer(myfile)
writer.writerow([username,password,firstname,surname,age])
myfile.close()
menu()
def login():
user0 = input("Username: ")
pass0 = input("Password: ")
file = open("account.txt","r")
for line in file:
details = line.split(",")
if user0 == details[0] and pass0 == details[1]:
print("Correct!")
else:
print("Fail")
menu()
def menu():
selection = int(input("1 or 2: "))
if selection == 1:
register()
else:
login()
menu()
Your main problem is identation - your if user0 == details[0] and pass0 == details[1]: is on the same indentation as the for line in file:- meaning it is executed after the for-loop not inside it and for each details. You are currently only ever checking the last detail you parse from your file.
You can fix this by indenting it correctly.
This would then lead to multiple outputs - if your user is on line 100 it will print 99 fails and 1 correct - thats why I would put the printing outside the for loop. You can use break to abort the loop as soon as you found the correct user.
Changing your login to this will accomplish that:
def login():
user0 = input("Username: ")
pass0 = input("Password: ")
file = open("account.txt","r")
foundOne = False
for line in file:
details = line.split(",")
# execute Check on each line, not only on last line
if user0 == details[0] and pass0 == details[1]:
foundOne = True
break # this will instantly leave the for loop of line checkings
if foundOne == True:
print("Correct!")
else:
print("Fail")
menu()
I indented the if ... so it is done for each line instead of only once. I also set a status to avoid printing Fail for each checked line.
Make sure to use the correct username - it is a combination of firstname and age
Let me start by saying that I don't like to do complete rewrites if I can avoid it, I prefer to give the answer to the problem with as much of the original code in place.
The reason your code doesn't do what you expect is this bit:
for line in file:
details = line.split(",")
That only gives you the last line fed in as details is essentially overwritten every time the loop reads the next line in the file. You then come out of that for loop and check against details, so it only knows about the last line.
There's a number of ways you could go about this, I would suggest that the easiest is to use a dictionary instead of a list so that you can fill it up with the contents of the users file. You can also use csv.reader to read the csv file you created straight into a list without needing to split it first:
import csv
def login():
user_dict = {}
with open("account.txt", "r") as csvfile:
authfile = csv.reader(csvfile)
for line in authfile:
user_dict[line[0]] = line[1:]
user0 = input("Username: ")
if user_dict.get(user0):
pass0 = input("Password: ")
if user_dict.get(user0)[1] == pass0:
print("Correct!")
menu()
else:
print("Bad Password")
else:
print("Bad Username")
The first section creates the user dictionary and fills it with the details you've saved to file. First entry (username) is the key and the rest of the details are stored in a list under that key.
From there, we get the username and then do a get request on the dictionary to make sure the user exists (dict.get() will return None if it fails and won't raise an exception). If the user exists, we ask for their password and check it. If the password matches it prints out the affirmative answer and loads your menu function. If not, the user is notified that they've supplied a bad password.
I hope that all made sense. Let me know if you have any questions.
edit: I may have misread this one. It looks like everything leads back to the menu function no matter what. I do believe I've engaged in a bit of overkill.

Existing file not appending new record

I am trying to create a file as the header and then open it later to append new records, but it seems I am not doing something correctly, does anyone have an idea?
here is the code below:
I have tried it in several ways to no avail.
file = 'Quizdata5.txt'
users = {}
def header():
headers = ("USERID LOGIN-NAME SURNAME NAME AGE "
" YEAR-GROUP SEX USERNAME\n")
with open(file, 'w') as file1:
file1 .write(headers)
file1.close()
def newUser():
global users
global header
global createLogin
global createPassw
global surname
global name
global age
global y_group
global sex
global z1
createLogin = input("Create login name: ")
if createLogin in users: # check if login name exists
print("\nLogin name already exist, please choose a different name!\n")
else:
createPassw = input("Create password: ")
users[createLogin] = createPassw # add login and password
#return (users[createLogin])
surname = input("Pls enter your surname: ")
name = input("Pls enter ur name: ")
age = input("Pls enter your age: ")
y_group = int(input("Please enter your year group: "))
sex =input("Please enter your sex: ")
print("\nUser created!\n")
print("*********************************")
print(" Your Name is\t" + name, "and it starts with: " + name[0] + "\n")
z1 = createPassw[:3] + age
print(" Your Username is:\t ", z1)
if __name__ =='__main__':
header()
while newUser():
with open(file, 'a') as file2:
rows = ("{:8} {:8} {:8} {:8} {:8} {:8}"
" {:8} {:8} \n".format(createLogin, createPassw,
surname, name, age,
y_group, sex, z1))
file2.write(rows.split())
file2.close()
#enter code here
Working version below. Note that I changed your input statements to raw_input. I'm using Python 2.7. Main things needed:
a choice to exit outside AND inside the while loop
build a list for existing users for the existing username check
fixing your formatting for row
Not splitting your row when you write it
Seems to be working now and ready for more improvements. Build a little and test until working, then build more - saves a ton of time!
file = 'Quizdata5.txt'
users = {}
def header():
headers = "USERID LOGIN-NAME SURNAME NAME AGE YEAR-GROUP SEX USERNAME\n"
with open(file, 'r') as file1:
firstLine = file1.readline()
print firstLine
if firstLine == headers:
print 'Headers present'
return
with open(file, 'w') as file1:
file1.write(headers)
def newUser():
userList = []
with open(file, 'r') as file1:
Lines = file1.readlines()
for line in Lines[1:]:
lineArray = line.split(' ')
userList.append(lineArray[0])
print userList
global users
global header
global createLogin
global createPassw
global surname
global name
global age
global y_group
global sex
global z1
createLogin = raw_input("Create login name or enter 'exit' to quit: ")
if createLogin == 'exit':
return False
while createLogin in userList: # check if login name exists
print("\nLogin name already exist, please choose a different name!\n")
createLogin = raw_input("Create login name or enter 'exit' to quit: ")
createLogin = createLogin.strip()
if createLogin == 'exit':
print('Goodbye for now.')
return False
createPassw = raw_input("Create password: ")
users[createLogin] = createPassw # add login and password
# return (users[createLogin])
surname = raw_input("Pls enter your surname: ")
name = raw_input("Pls enter ur name: ")
age = raw_input("Pls enter your age: ")
y_group = int(raw_input("Please enter your year group: "))
sex = raw_input("Please enter your sex: ")
print("\nUser created!\n")
print("*********************************")
print(" Your Name is\t" + name, "and it starts with: " + name[0] + "\n")
z1 = createPassw[:3] + age
print(" Your Username is:\t ", z1)
return True
if __name__ =='__main__':
header()
while newUser() == True:
with open(file, 'a') as file2:
row ="{a} {b} {c} {d} {e} {f} {g} {h}\n".format(
a=createLogin, b=createPassw, c=surname, d=name, e=age, f=y_group, g=sex, h=z1)
file2.write(row)
Without just rewriting your code outright, your problem is the line
while newUser():
This means call newUser(), and execute the indented code only if the return value of newUser(), evaluated as a boolean, returns True. That is bool(newUser()) is True.
Now the questions are
a) What does newUser() return and,
b) What does bool() mean?
First b: All objects in Python have some "boolean" value associated with it, True or False. For a lot of built-in types their boolean evaluation makes sense. For example the integer 0 is treated as False in a boolean context, while any non-zero integer is treated as True. This is the case in most any programming language with some exceptions.
Similarly an empty list [] is False in a boolean context (which is why we can write things like if not my_list: ... to test if a list is empty) while any non-empty list is treated as True and so on.
As for a:
Your newUser() function doesn't explicitly return and any result, because you don't have a return statement (Tom's solution added some). What you want to do is return a True-ish value when a new user is added, and a False-ish value when no new users are to be added. But since you don't return anything, in fact, the default return value for functions if Python, if you don't explicitly return, is a value called None and it is always False.
So the end result is that the code under your while statement is never run.
If you're ever in doubt about what your code is doing walk through it line by line and see exactly what it's doing--what functions are returning and what values are being assigned to variables--by using the pdb debugger (Google will direct you quickly to some good tutorials). With Python in particular there's no reason to ever be in the dark about what your code is actually doing.

Searching a .CSV file

I've been trying to create a program in python whereby you can access, search and input(append) the data in a CSV file. I am able to append and print the file, however I am having trouble searching the external file.
This is what my code looks like so far:
def a():
# knows to use the file (getting something that's made)
import csv
myfile = open("student01.csv", "a")
student_num = input("Enter the student number: ")
name = input("Enter student's name: ")
tutor_group = input("Enter the tutor group: ")
gender = input("Enter M or F: ")
new_record =student_num+","+name+","+tutor_group+","+gender
myfile.write(str(new_record))
myfile.write("\n")
myfile.close()
def d():
# knows to use the file (getting something that's made)
import csv
myfile = open("student01.csv", "rb")
reader = csv.reader(myfile)
for row in myfile:
print(row)
myfile.close()
def menu():
print("Welcome to Student.csv\nWhat would you like to do?")
print()
print("1. Add to the file")
print("2. Display all the data from the file")
print("3. Search for particular data")
enter = input("Enter 1, 2 or 3: ")
enter = enter.upper()
if enter == "1":
a()
elif enter == "2":
d()
else:
s()
menu()
I'm just not sure what to do now for my def s(): so that I am able to search for a student in the file by their name, number or tutor group.
Does anyone have any ideas?
Lotz
import csv
def create_record(number_of_students):
while number_of_students:
student_num = raw_input("Enter the student number: ")
name = raw_input("Enter student's name: ")
tutor_group = raw_input("Enter the tutor group: ")
gender = raw_input("Enter M or F: ")
if student_num and name and tutor_group and gender:
record_list = [student_num, name, tutor_group, gender]
with open("student_record.csv", "ab") as wf:
writer = csv.writer(wf)
writer.writerow(record_list)
number_of_students -= 1
def display_record(option):
with open("student_record.csv", "r") as rf:
reader = csv.reader(rf)
if option == 2:
for row in reader:
print " ".join(row)
elif option == 3:
search_feild = raw_input("Search by student name, number, tutor_group, gender :")
for row in reader:
if search_feild in row:
print " ".join(row)
def main():
print("1. Add to the file")
print("2. Display all the data from the file")
print("3. Search for particular data")
print("0. To Exit")
choice = True
while choice:
your_choice = input("Enter your choice:")
if your_choice == 1:
number_of_students = input("Enter number of records you want to enter:")
create_record(number_of_students)
if your_choice == 2:
display_record(2)
if your_choice == 3:
display_record(3)
if your_choice == 0:
choice = False
if __name__ == "__main__":
main()
Output:
1. Add to the file
2. Display all the data from the file
3. Search for particular data
0. To Exit
Enter your choice:1
Enter number of records you want to enter:3
Enter the student number: 1
Enter student's name: Jhon
Enter the tutor group: Python
Enter M or F: M
Enter the student number: 2
Enter student's name: Lina
Enter the tutor group: Django
Enter M or F: F
Enter the student number: 3
Enter student's name: Max
Enter the tutor group: Python
Enter M or F: M
Enter your choice:2
1 Jhon Python M
2 Lina Django F
3 Max Python M
Enter your choice:3
Search by student name, number, tutor_group, gender :Python
1 Jhon Python M
3 Max Python M
Enter your choice:3
Search by student name, number, tutor_group, gender :F
2 Lina Django F
Enter your choice:0
You should even write your data in csv file using csv writer method.
Searching is easy as while reading a csv it gives a list in which we can search any element by using in keyword.
There is a DictReader in the csv module, perfect for what you want to do (assuming some fields are unique, like student_num probably)
just for info I see some problems in your code
don't import module in function if not necessary, and don't repeat yourself(DRY), just put one import statement at the top outside any function, and if you import something, make use of it ;)
use function's parameters instead of harcoding literals constant inside the body for file name
this : student_num+","+name+","+tutor_group+","+gender should be removed, use ', '.join(your_iterable) instead
when you want to open a file and do work on it before close it, use a context manager : `with open('myfile.txt') as flux:', it defines a block where the file is opened, the file will be closed automatically, even if a problem occurs and an exception is raised
Searching through a set of records is not a trivial problem. I hope this won't make your like super complicated but you'll need a couple of things:
Indices for each field you would like to search on (a data structure that copies information for fast lookup)
A clever way of guessing whether the user is entering a name, tutor group or number (or just asking them what they want to search by)
You can make your own stuff here: maybe start by compiling the users' input into a regular expression and search subsets of the CSV file (like the name column) by doing binary comparisons between the entry and your user's query.
You can also make an index: just pick a data type (or make your own of course) and make sure it's super efficient for checking through itself in a reasonable amount of time for the number of records you have (as low a time complexity as possible).
Then again, a lot of people have been working on this problem for a long time and have TONS of code out there to help you. Check out Information Retrieval and get a feel for the type of problem you are looking at.
You can use something like Xapian for search but there are a lot of alternatives.
Here are some SO questions that might help you: the one without a chosen answer, the one that uses the anyfunction, and the one about getting the right look at columns

Categories