Using user input to search through an established dictionary - python

I'm trying to get through my first semester of Python and am struggling. My dictionary is correct however, I cannot get what I want. I need the user to input a patient ID and then the program will display the ID with the name linked to it in the dictionary as the name is the value. Then if the user enters an ID that is not in the dictionary the computer tells them so. If they enter done the program says DONE! When numbers are entered the program needs to continue asking the question until done is typed. Here is was I have so far:
patientinfo = {}
lines = open('PatientsNames.txt')
lines.readline()
for line in lines:
id=line[:8]
if id not in patientinfo:
endlastname = line.find(' ', 8)
lastname = line[8:endlastname]
firstname = line[endlastname+1:]
patientinfo[id] = lastname + ', ' + firstname
answer = raw_input("Enter an ID ('done' to exit)")
try:
if answer in patientinfo.keys():
print answer, patientinfo(val)
except:
if answer not in patientinfo.keys():
print 'No patient with that ID'
else:
if answer='done':
print 'DONE!'

Related

How can I send a routine email using a list as input?

I'm trying to write code in Python to help with sending an email that I send about twice a week, with the same format every time and just a few elements that differ between emails, so I wrote the following code to help with this:
def visitor():
visitors = []
number_of = int(input("How many visitors are you signing in? "))
time = input("What time are they coming? ")
comments = """
Please type the name of the first visitor, and their nationality on the next line, the name of the second visitor
and their nationality on the next line, until you wrote down all the names and nationalities.
If you wanna stop the program and execute the code with the names & nationalities, just type quit
"""
print(comments)
name, i = "", 1
while name != "quit":
name = str(input("Ignore: "))
visitors.append(name)
visitors = visitors.pop(-1)
email = f"""
Hello,
I have {number_of} visitors coming today at {time}.
Name: {visitors[i]}
Nationality: {visitors[i + 1]}
"""
for i in range(len(visitors)):
to_add = f"""
Name: {visitors[i]}
Nationality: {visitors[i + 1]}
"""
email += to_add
ending = "Awaiting your approval\nThank you"
email += ending
return email
visitor()
However, upon running this code, I run into a problem in line 25, saying "Index out of range" ( line 25 is Nationality: {visitors[i + 1]} ). This normally shouldn't happen since the list has more than one element. Can someone help with this?
P.S. I have another, way longer code written for this that works, but I wanted to try and improve it by making it less sloppy.
The visitors list is acceeded at offset i+1, and i go up to len(visitors)-1 (upper limit specified for the loop through range()), so there is an access out of range when i = len(visitors) - 1

Why does one of my login functions work and the other does not, despite the fact that they both have the identical code?

So I am trying a login system for my bank management project and I created two of the login system.
one for the admin system and the other for the customer. This is the code and text file for both. Why would my first function work and not the second? FYI I can't use any global function and dictionary and the error I been getting is ValueError: too many values to unpack (expected 2)
def LAdminAccount():
EnteredStaffAccountNumber = str(input("========== Please Type in Your Account Number:"))
EnteredStaffPassword = str(input("========== Please Type in Your Password:"))
A= open("AdminUser.txt","r")
for line in A.readlines():
us,pw = line.strip().split("|")
if (EnteredStaffAccountNumber == us ) and (EnteredStaffPassword == pw):
print ("Login successful")
A.close()
AdminMenu()
print ("Wrong username/password")
return
def LCustomerAccount():
EnteredID = str(input("========== Please Type in Your Account ID:"))
EnteredPassword = str(input("========== Please Type in Your Password:"))
B= open("Customerlogin.txt","r")
for line in B.readlines():
id,pw = line.split("|",1)
print (id)
print (pw)
if (EnteredID == id ) and (EnteredPassword == pw):
print ("Customer Login successful")
B.close()
CustomerMenu()
print ("Wrong Account Number/password")
menu()
AdminUser.txt
00001|1234
Customerlogin.txt
000403100865|3088
Output is:
000403100865
3088
Customer Login successful
Wrong Account Number/password
The error suggests that the problem is the following line:
id,pw = line.split("|")
If you have more than one "|" in your text your will not be able to split them this way.
To guarantee the string is split at most once try replacing with:
id,pw = line.split("|", 1)

Python List Index Ouf Of Range In IF Statement

So i have multiple patients' information stored in database.txt and i want to retrieve the data from the file into a list.
And the system prompt for patient's id to search and display other information of the patient such as Name, Age, Group & Zone.
However, i'm getting error from line 12, but the similar syntax in line 17 is able to run without problem.
search_keyword = input() # Asks for patient's name or id (either one)
with open("database.txt", "r") as database:
for data in database:
for patients in data.split('|'):
patient_details = []
for details in patients.split(','):
patient_details.append(details)
print(patient_details) # test
print(len(patient_details) # test
print(patient_details.index('Patient001')) # test
print(patient_details[4]) # test
if search_keyword == patient_details[0] or search_keyword == patient_details[4]: # error occured here, where it says list index out of range.
print("Name: " + patient_details[0])
print("Age: " + patient_details[1])
print("Group: " + patient_details[2])
print("Zone: " + patient_details[3])
print("ID: " + patient_details[4]) # no error here, patient_details[4] is able to display patient's id
database.txt
John,18,A,1,Patient001|Nick,20,F,9,Patient002
Test command for line 8,9, 10 and 11:
Line 8: [John, 18, A, 1, Patient001]
Line 9: 5
Line 10: 4
Line 11: IndexError: list index out of range
Can someone explain why this is happening, and any solutions regarding this issue without using any imported modules? Thank you for any assistance.
Imo a very good use-case for a named tuple:
from collections import namedtuple
text = "John,18,A,1,Patient001|Nick,20,F,9,Patient002"
# build database
Patient = namedtuple('Patient', ['name', 'age', 'group', 'zone', 'id'])
db = [Patient(*patient) for entry in text.split("|") for patient in [entry.split(",")]]
# Asks for patient's id
search_keyword = input("Please give an ID: ")
# query the database
result = [patient for patient in db if patient.id == search_keyword]
# or patient.id.startswith(), etc.
print(result)
Without any imported modules, you could use
text = "John,18,A,1,Patient001|Nick,20,F,9,Patient002"
# build database
db = [entry.split(",") for entry in text.split("|")]
search_keyword = input("Please give an ID: ") # Asks for patient's id
# query the database
result = [patient for patient in db if patient[4] == search_keyword]
print(result)
I see no flaw in the code. Although, I can point out a few ways to optimise it :
patient_details = dict()
with open("database.txt", "r") as database:
for data in database:
for patients in data.split('|'):
patients = patients.split(',')
patient_details[patients[4]] = patients[0:4]
search_keyword = input() # Asks for patient's id
if patient_details.get(search_keyword, None):
patient_detail = patient_details[search_keyword]
print("Name: " + patient_detail[0])
print("Age: " + patient_detail[1])
print("Group: " + patient_detail[2])
print("Zone: " + patient_detail[3])
print("ID: " + search_keyword)
Using map instead of a linear search would allow you to search optimally.

"Cannot deserialize instance of string from START_ARRAY value" Salesforce API issue

Trying to create a SF Contact with values from an .xlsx sheet.
I can create a contact if I manually type in a fake email address, lastname and firstname but cannot reference it to a value I have defined from an xlsx sheet.
the print commands are working fine and reading the appropriate data I want them to read.
Only been doing Python for 2 weeks now and have already been able to read, write and save data to/from MySQLdb without issue but now running into this issue and not finding much info on this specifically with SalesForce. Any help would be greatly appreciated.
So the full error is:
File "C:\Python27\lib\site-packages\simple_salesforce-0.70-py2.7.egg\simple_salesforce\api.py", line 749, in _exception_handler
raise exc_cls(result.url, result.status_code, name, response_content)
simple_salesforce.api.SalesforceMalformedRequest: Malformed request https://na48.salesforce.com/services/data/v37.0/sobjects/Contact/. Response content: [{u'errorCode': u'JSON_PARSER_ERROR', u'message': u'Cannot deserialize instance of string from START_ARRAY value [line:1, column:2]'}]
Email = sheet.col_values(1, 1)
Last = sheet.col_values(2, 1)
First = sheet.col_values(3, 1)
print Email
print Last
print First
sf.Contact.create({'LastName' : Last,'FirstName' : First,'Email' : Email})
Okay, Error is fixed but it only creates one contact/case on salesforce which is the last row in the xlsx sheet rather than creating a contact/case for each row in the xlsx. It reads everything for the most part correctly and does in fact create a contact the correct way but only the last row.
Current Code:
for c in range(sheet.ncols):
for r in range(sheet.nrows):
Email = sheet.col_values(1,r)[0]
print Email
Last = sheet.col_values(2,r)[0]
print Last
First = sheet.col_values(3,r)[0]
print First
Phone = sheet.col_values(4,r)[0]
print Phone
Street = sheet.col_values(5,r)[0]
print Street
City = sheet.col_values(6,r)[0]
print City
Postal = sheet.col_values(7,r)[0]
print Postal
Product = sheet.col_values(8,r)[0]
print Product
Store = sheet.col_values(9,r)[0]
print Store
SN = sheet.col_values(10,r)[0]
print SN
Name = sheet.col_values(3,r)[0]+sheet.col_values(2,r)[0]
sf.Contact.create({'FirstName' : First, 'LastName' : Last, 'Email' : Email, 'Phone' : Phone, 'MailingStreet' : Street, 'MailingCity' : City, 'MailingPostalCode' : Postal})
The error message from the server says
Cannot deserialize instance of string from START_ARRAY value [line:1,
column:2]
meaning that the server is expecting a field value to be a string, but the request has an array instead.
Therefore guessing that sheet.col_values() returns an array, you'd want to change it to
Email = sheet.col_values(1, 1)[0]
Last = sheet.col_values(2, 1)[0]
First = sheet.col_values(3, 1)[0]
Updated for 2nd issue:
Indents are significant in python, your create call only happens once because its outside the loop, you need to move it inside the loop, e.g.
for c in range(sheet.ncols):
for r in range(sheet.nrows):
Email = sheet.col_values(1,r)[0]
print Email
Last = sheet.col_values(2,r)[0]
print Last
First = sheet.col_values(3,r)[0]
print First
Phone = sheet.col_values(4,r)[0]
print Phone
Street = sheet.col_values(5,r)[0]
print Street
City = sheet.col_values(6,r)[0]
print City
Postal = sheet.col_values(7,r)[0]
print Postal
Product = sheet.col_values(8,r)[0]
print Product
Store = sheet.col_values(9,r)[0]
print Store
SN = sheet.col_values(10,r)[0]
print SN
Name = sheet.col_values(3,r)[0]+sheet.col_values(2,r)[0]
sf.Contact.create({'FirstName' : First, 'LastName' : Last, 'Email' : Email, 'Phone' : Phone, 'MailingStreet' : Street, 'MailingCity' : City, 'MailingPostalCode' : Postal})

How to test if a dictionary (in an external file) contains the user inputted username (Python3 )?

I am building a Flea Market program. I have an external file hosting all the usernames and passwords of employees. I am trying to test the login section, asking for username then password. It tests if the UN is in the dictionary contained in the readline().
Here is the external file with the usernames and passwords. :
managers = {"manager":"password", "owner":"apple"}
employees = {"jane":"none", "john":"banana"}
And here is the code.:
print("Welcome to Flea Master 2000...\n")
read_employee_file = open('employees_list.txt', 'r')
managers = read_employee_file.readline(0)
employees = read_employee_file.readline(1)
print(managers)
read_employee_file.close()
user_id = input("User ID:\n")
user_password = input('Password:\n')
if user_id in managers[:]:
if managers[user_id] == user_password:
print("Welcome, {0}.".format (user_id))
user_status='manager'
if user_id in employees:
if employees[user_id] == user_password:
print("Welcome, {0}".format (user_id))
user_status = 'staff'
if user_status == 'manager':
action_manager = int(input("Options: (Input number to select...)\n1) Add employee.\n2) Remove employee.\n"))
if action_manager == 1:
employee_addition_type=input("What kind of employee is he/she? ('manager' or 'staff')")
if employee_addition_type == 'manager':
new_manager_username = input("Enter the new manager's username...\n")
new_manager_password = input("Enter the new manager's password...\n")
managers[new_manager_username] = new_manager_password
else:
new_staff_username = input("Enter the new staff member's username...\n")
new_staff_password = input("Enter the new staff member's password...\n")
employees[new_staff_username]=new_staff_password
if action_manager == 2:
print("The list of current employees is: \n")
for key in all_staff:
print(key)
print('\n')
which_remove = input("Now, which do you want to remove? Enter the username exactly.\n")
if which_remove in managers:
del managers[which_remove]
else:
del employees[which_remove]
print("\nDone. Updated roster is:\n")
all_staff = dict(managers, **employees)
for key in all_staff:
print(key
)
Your readline lines are a bit incorrect. The argument to readlines is the maximum number of bytes it will read. So readlines(6) doesn't mean "read the sixth line", it means "read no more than six characters from the current line". I suggest just doing read_employee_file.readline(), with no argument.
managers = read_employee_file.readline()
employees = read_employee_file.readline()
Now you have the full contents of each line, but both variables are still strings. However, you could use the json module to load those dictionaries.
import json
line = 'managers = {"manager":"password", "owner":"apple"}'
#chop off the left part of the string containing "managers = "
line = line.partition(" = ")[2]
d = json.loads(line)
print "the owner's password is", d["owner"]
if "bob" not in d:
print "can't find bob's password in managers dictionary!"
Result:
the owner's password is apple
can't find bob's password in managers dictionary!
There are several ways to read and parse your input file. Assuming your file is the way you specified and you are willing to handle the exceptions, here is one sample method for you. You need to handle exceptions approriately.
try:
#This will read your in.conf which contains user/pwds in the dictionary format you specified.
#Read documentation on exec here:
# https://docs.python.org/3.0/library/functions.html#exec
with open('in.conf') as fh:
for line in fh:
exec(line)
user_id = input("User ID:\n")
user_password = input('Password:\n')
if user_id in managers and user_password == managers[user_id]:
print("Welcome, {0}.".format (user_id))
user_status='manager'
elif user_id in employees and user_password == employees[user_id]:
print("Welcome, {0}.".format (user_id))
user_status='staff'
else:
print "invalid credentials"
except NameError:
#catch situations where your file doesn't contain managers or employees dictionary
#I just raise it so you can see what it would print
raise
except:
#other exceptions as you see appropriate to handle ....
#I just raise it so you can see what it would print
raise

Categories