Matching user input to file records in Python - python

i'm making a program that will ask a user to enter their student ID and it will display the student information such as student ID and their student name . i does this first by asking the user to enter their id and it will then read a .txt file and check if the student id is a matched then it will print out the content of my .txt file information of the specific student that the user is looking for.
this is my content of the file
201707001 Michael_Tan
201707002 Richard_Lee_Wai_Yong
201707003 Jean_Yip
201707004 Mark_Lee
201707005 Linda_Wong
201707006 Karen_Tan
201707007 James_Bond
201707008 Sandra_Smith
201707009 Paul_Garcia
201707010 Donald_Lim
this is my source code
# user can find out the student info
userInput = input("Please enter a student ID: ")
# read the students file
with open('C:\\Users\\jaspe\\Desktop\\PADS Assignment\\Student.txt') as f:
studentFile = f.readlines()
for student in studentFile:
stdId, stdName = student.strip().split(" ",1)
# check if the student exist
matched = True
while matched:
if userInput == stdId:
print("True")
else:
print("False")
matched = False
break
but the output i get is false even though i type the exact studentID

You should perform your checks as you read your file. Otherwise, you are splitting and obtaining your information, but this data is lost in the subsequent iteration. Try this:
with open('C:\\Users\\jaspe\\Desktop\\PADS Assignment\\Student.txt') as f:
studentFile = f.readlines()
for student in studentFile:
stdId, stdName = student.strip().split()
if userInput == stdId:
print(stdName)
break
Better still, for large files, iterate line-wise. Do not use f.readlines because it loads all your data into memory.
with open('C:\\Users\\jaspe\\Desktop\\PADS Assignment\\Student.txt') as f:
for line in f:
stdId, stdName = line.strip().split()
if userInput == stdId:
print(stdName)
break

As it stands your code loops through every ID and name and assigns each into the stdId and stdName, but that loop exits before you check for a match... Because of that it only holds the last value stored in those variables by the loop. You need the check in the loop, as so
# user can find out the student info
userInput = input("Please enter a student ID: ")
# read the students file
with open('C:\\Users\\jaspe\\Desktop\\PADS Assignment\\Student.txt') as f:
studentFile = f.readlines()
for student in studentFile:
stdId, stdName = student.strip().split(" ",1)
# check for a match here, break the loop if a match is found

Use raw_input instead of input.
You almost never want to use input, because it does evaluation. In this case, typing in an exact integer gives you an integer, while the file gives you a string, so it won't match.
You have other minor / major issues in the code.
If the loop is entered with userInput == stdId you will loop forever printing True.
You never actually search through the student ids, you just check the last one set in your previous loop
(For this I would recommend using a dictionary if you plan to do multiple user queries, or just look as you read the lines of the file for a simple script)

Related

Is there any easy way to check for duplicates in a text file in Python?

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]

Loop through a text file with an input

I have a text file set out in this layout:
Greg,Computer Science,Hard,5
Alex,Computer Science,Medium,2
Fiona,Maths,Easy,0
Cassie,Maths,Medium,5
Alex,Maths,Medium,1
In my program I want the user to be able to choose a certain name and see their results. My code for this looks like this:
name = input("Enter name: ")
for each in file:
each = each.split(",")
realName = each[0]
subject = each[1]
difficulty = each[2]
score = each[3]
if name == realName:
print(subject, difficulty, score)
break
else:
print()
print("Invalid name.")
name = input("Re-enter your name: ")
A few things are wrong with it though and I can't figure out what to do:
If the user entered "Alex", only one of his results will be displayed.
If a wrong name is inputted once, every other name inputted will return as "Invalid".
If the correct name is inputted and the results are displayed, the program will continue to ask for a name.
Does anybody have any solutions to these problems?
If you're going to query your file repeatedly, I'd recommend pre-loading your data once into a dictionary, and printing data as and when needed. Something like this:
data = {}
with open('file.txt', 'r') as file:
for line in file:
realName, subject, difficulty, score = each.split(',')
data.setdefault(realName, []).append((subject, difficulty, score))
while True:
name = input('>>> ')
data.get(name, 'Invalid Name')
This solves problems one and two. If you just want to break after the first valid name is input, you can query the return value of dict.get:
while True:
name = input('>>> ')
result = data.get(name)
if result:
print(result)
break
print('Invalid name')
This solves problem three.
You're better off using the csv module since your file syntax is simple CSV.
Then you can loop through the rows (each row will be an array of values).
import csv
def parse_csv_file(csv_file, operation, value, index):
with open(csv_file, newline='') as file:
reader = csv.reader(file, delimiter=',',
quotechar='|')
return operation(reader,
value, index)
def find_first_row(csv_reader, value, index):
for row in csv_reader:
if row[index] == value:
return row
return None
def main():
query = input('Enter a name: ')
result = parse_csv_file('file.csv',
find_first_row,
query, 0)
if result:
print(result)
else:
print('Nothing found!')
main()

How do i find if a whole word is in a text file?

My code looks like this:
file = open('names.txt', 'r')
fileread = file.read()
loop = True
while loop is True:
with open('names.txt', 'r') as f:
user_input = input('Enter a name: ')
for line in f:
if user_input in line:
print('That name exists!')
else:
print('Couldn\'t find the name.')
The code basically asks the user for a name, and if the name exists in the text file, then the code says it exists, but if it doesn't it says it couldnt find it.
The only problem I have is that if you even enter part of the name, it will tell you the whole name exists. For example the names in my text file are: Anya, Albert and Clemont, all seperated on different lines. If i were to enter 'a' when prompted for user_input, the code will still say the name is present, and will just ask for another name. I understand why its doing this, because 'a' is technically in the line, but how do i make it so that it only says the name exists if they enter the whole thing? By whole thing i mean they enter for example 'Anya', rather than 'a' and the code only says the name exists if they enter 'Anya'. Thanks
Short solution using re.seach() function:
import re
with open('lines.txt', 'r') as fh:
contents = fh.read()
loop = True
while loop:
user_input = input('Enter a name: ').strip()
if (re.search(r'\b'+ re.escape(user_input) + r'\b', contents, re.MULTILINE)):
print("That name exists!")
else:
print("Couldn't find the name.")
Test cases:
Enter a name: Any
Couldn't find the name.
Enter a name: Anya
That name exists!
Enter a name: ...
To answer the question , just do equal comparison. Also noted that You have infinite loop , is that expected ? I changed the code to exit that loop when a matching name found in the file
file = open('inv.json', 'r')
fileread = file.read()
loop = True
while loop is True:
with open('inv.json', 'r') as f:
user_input = raw_input('Enter a name: ')
for line in f:
if user_input == line.strip():
print('That name exists!')
break
#loop =False
else:
print('Couldn\'t find the name.')
Input
Anya
Albert
Clemont
Output
Enter a name: an
Couldn't find the name.
Couldn't find the name.
Couldn't find the name.
Enter a name: An
Couldn't find the name.
Couldn't find the name.
Couldn't find the name.
Enter a name: Any
Couldn't find the name.
Couldn't find the name.
Couldn't find the name.
Enter a name: Anya
That name exists!

Python 3.3 dump and load pickled dictionary

I am working through the chapter exercises in Tony Gaddis's "Starting Out With Python" 3rd edition from a class I have taken previously. I'm in chapter 9 and Exercise 8 requires me to write a program that pickles a dictionary (name:email) to a file when it closes and unpickles that file retaining the data when it is opened. I have read every word in that chapter and I still don't understand how you can do both in the same file. When you use the open function it creates a file which, in my understanding, is a new file with no data. I'm thinking it may be a sequencing issue, as in where to put the dump and load lines of code but that doesn't make sense either. Logic dictates you have to open the file before you can dump to it.
If the 'open' function creates a file object and associates it with a file and this function appears early in the code (as in def main), what keeps it from zeroing out the file each time that line is called?
This is not a homework assignment. I have completed that class. I am doing this for my own edification and would appreciate any explanation which would help me to understand it. I have included my attempt at the solution which is reflected in the code below and will keep gnawing at it until I find the solution. I just thought since the gene pool is deeper here I would save myself some time and frustration. Thank you very much to those that choose to reply and if I am lacking in any pertinent data that would help to clarify this issue, please let me know.
import pickle
#global constants for menu choices
ADDNEW = 1
LOOKUP = 2
CHANGE = 3
DELETE = 4
EXIT = 5
#create the main function
def main():
#open the previously saved file
friends_file = open('friends1.txt', 'rb')
#friends = pickle.load(friends_file)
end_of_file = False
while not end_of_file:
try:
friends = pickle.load(friends_file)
print(friends[name])
except EOFError:
end_of_file = True
friends_file.close()
#initialize variable for user's choice
choice = 0
while choice != EXIT:
choice = get_menu_choice() #get user's menu choice
#process the choice
if choice == LOOKUP:
lookup(friends)
elif choice == ADDNEW:
add(friends)
elif choice == CHANGE:
change(friends)
elif choice == DELETE:
delete(friends)
#menu choice function displays the menu and gets a validated choice from the user
def get_menu_choice():
print()
print('Friends and Their Email Addresses')
print('---------------------------------')
print('1. Add a new email')
print('2. Look up an email')
print('3. Change a email')
print('4. Delete a email')
print('5. Exit the program')
print()
#get the user's choice
choice = int(input('Enter your choice: '))
#validate the choice
while choice < ADDNEW or choice > EXIT:
choice = int(input('Enter a valid choice: '))
#return the user's choice
return choice
#the add function adds a new entry into the dictionary
def add(friends):
#open a file to write to
friends_file = open('friends1.txt', 'wb')
#loop to add data to dictionary
again = 'y'
while again.lower() == 'y':
#get a name and email
name = input('Enter a name: ')
email = input('Enter the email address: ')
#if the name does not exist add it
if name not in friends:
friends[name] = email
else:
print('That entry already exists')
print()
#add more names and emails
again = input('Enter another person? (y/n): ')
#save dictionary to a binary file
pickle.dump(friends, friends1.txt)
friends1.close()
#lookup function looks up a name in the dictionary
def lookup(friends):
#get a name to look up
name = input('Enter a name: ')
#look it up in the dictionary
print(friends.get(name, 'That name was not found.'))
#the change function changes an existing entry in the dictionary
def change(friends):
#get a name to look up
name = input('Enter a name: ')
if name in friends:
#get a new email
email = input('Enter the new email address: ')
#update the entry
friends[name] = email
else:
print('That name is not found.')
#delete an entry from the dictionary
def delete(friends):
#get a name to look up
name = input('Enter a name: ')
#if the name is found delete the entry
if name in friends:
del [name]
else:
print('That name is not found.')
#call the main function
main()
If you open a file for reading with open("my_file","r") it will not change the file. The file must already exist. If you open a file for writing with open("my_file","w") it will create a new file, overwriting the old one if it exists. The first form (reading) is the default so you can omit the second "r" argument if you want. This is documented in the Python standard library docs.
Use open("myfile", 'r+') this allows both read and write functions. (at least in 2.7)

Struggling with Python

I must answer this question in python but I'm not sure what i must do, this is the question:
Your program should read in multiple lines of input from the user, stopping when the user enters a blank line. Each line will be a command from the user to the phone. Each command consists of a space-separated sequence of words.
If the first word is Add, there will be two words following it: the name of the person and their phone number. If an Add command is encountered, your program should store this name to phone number mapping. Alternatively, if the first word is Call, there will be one word following it: the name of the person to call. In this case, if the phone knows the number for this person, your program should print out that it is calling that number, otherwise it should print out that it does not have a number for this person.
The program I have written is this:
contact = {}
**line = input('Command: ')
while line:
parts = line.split()
name = parts[0]
number = parts[1]
contact[name] = int(number)
line = input('Command: ')**
What more should I add or do to make this program work?
You need to distinguish the different commands.
contact = {}
line = input('Command: ')
while line:
parts = line.split()
command = parts[0]
if command == 'Add':
contact[parts[1]] = parts[2]
elif command == 'Call':
pass
# add the code to find the number and print it
line = input('Command: ')**
To start with you need to add a loop to keep asking the user for a command until they enter a blank line.
When writing an script which interacts with a user, it is also wise to think in terms of what the user could do wrong. The problem states a number of requirements, for example, if Add is entered, there should be two words following. If the user only entered one, what should you do?
Also what happens if the user enters a name that has not yet been entered? Python dictionaries provide a get() method which handles this. It allows you to specify what needs to be returned when the requested key is not present. In this case, you can return "Unknown name".
The following shows what I mean:
line = ' '
contacts = {}
while line:
line = input('Command: ')
if line:
words = line.split()
if words[0] == 'Add':
if len(words) == 3:
contacts[words[1].lower()] = words[2]
else:
print("Badly formatted Add")
if words[0] == 'Call':
if len(words) == 2:
print(contacts.get(words[1].lower(), "Unknown name"))
else:
print("Badly formatted Call")
By using the .lower() command on the entered name, it would then mean the user could do "Add Fred 1234 / Call fred" and it would still find a match.

Categories

Resources