importing and exporting from csv files - python

So I am trying to create a code which can search the data file:
By surname to retrieve and display the details for a contact
By date of birth to retrieve and display all contacts with a birthday in a particular month.
Here is the code I have created:
def search():
option = input('Please select to search by \n1. Surname\n2. D.O.B\n')
if option == '1':
surname = input('Please enter surname: ')
while not surname.isalpha():
surname = str(input('Please enter a valid surname: '))
Myfile = open('Address book.csv', 'rt')
for line in Myfile:
if ',' + str(surname) + ',' in line:
print(line)
else:
print('No contacts found')
elif option == '2':
Validmonth = False
while Validmonth == False:
month = input('Please enter the birth month')
if month >='13' and month <='0':
print('Please enter a valid month')
else:
Validmonth = True
Myfile = open ('Address book.csv', 'rt')
for line in Myfile:
if str(month) in line:
print(line)
else:
print('No contacts found')
else:
print('Error, select a valid option')
search()
search()
I keep getting this result when I try the code:
Please select to search by
1. Surname
2. D.O.B
1
Please enter surname: Vickers
No contacts found
No contacts found
No contacts found
No contacts found
No contacts found
No contacts found
No contacts found
No contacts found
I want to know why? someone please help?

You test for the surname on every row, then print No contacts found for every row that doesn't match.
Break out of the loop when you find the name, and use the else suite for the for loop instead:
for line in Myfile:
if ',' + str(surname) + ',' in line:
print(line)
break
else:
print('No contacts found')
else on a for loop only is executed if you exhausted the iterable, so when you did not break out of the loop early.
Your surnames are the first value on the line, so you would be better off testing if the line starts with the surname:
if line.startswith(surname + ','):
Pro tip: when reading CSV files, use the csv module:
import csv
with open('Address book.csv', newline='') as myfile:
reader = csv.reader(myfile)
for row in reader:
if row[0] == surname:
print(row)
break
else:
print('No contacts found')

Related

What am I doing wrong with the CSV part of my code

So, in my python code I'm supposed to prompt the user for their name, address, and phone number and write that data as a line of comma separated values to the file using the directory and filename. Everything runs except the CSV part.
import os
import csv
def file_system():
"""Display information about users"""
direc = input("Enter name directory to save a file: ")
filename = input("Enter name of the file they want to save to the directory: ")
name = input("Enter your name : ")
address = input("Enter your address : ")
phone_number = input("Enter your phone number : ")
print (direc, filename, name, address, phone_number)
prompt = input()
if os.path.isdir(direc):
writeFile = open(os.path.join(direc,filename),'w')
writeFile.write (direc, + filename)
writeFile.close()
print("File contents:")
readFile = open(os.path.join(direc,filename),'r')
for line in readFile:
print(line)
readFile.close()
if prompt:
with open('Userdata.csv', 'a',
newline='') as outfile:
w = csv.writer(outfile)
w.writerow(name, address, phone_number)
print("File Updated")
else:
print("Directory doesn't exist, please enter again")
file_system()
The issue is with the evaluation of the if statement before the csv section.
run the code below twice, first time just pressing enter, second time typing something and then pressing enter...
prompt = input("input something:\n")
if prompt:
print("you got here")
else:
print("you didn't")
As you can see, when only pressing enter, the if statement becomes False...

How to find a certain string/name in a txt file?

So im making a name generator/finder, So for the find command i want to find that name in the txt file with the line number! So how do i find the name with the line number?
line = 0
names = open(r"names.txt", "r")
name1 = names.readlines()
uname = input("Please enter the name you want to find: ")
for name in name1:
try:
print(name)
print(line)
if name == uname:
print(f"Found name: {name} \nLine No. {line + 1}")
else:
line = line + 1
except:
print("Unable to process")
But it seems to not work except if you write the last name in file it works. So could give any help?
EDIT: Ive found a way so you can reply if you want to for further people running into the problem!
Try this:
with open("names.txt", "r") as f:
file_contents = names.read().splitlines()
uname = input("Please enter the name you want to find: ")
for line, row in enumerate(file_contents):
if uname in row:
print('Name "{0}" found in line {1}'.format(uname, line))
Yo
if "namefilled" in name :
print("found it")
You can use pathlib if you have Python 3.4+. Pretty handy library.
Also, context management is useful.
# Using pathlib
from pathlib import Path
# https://docs.python.org/3/library/fnmatch.html?highlight=fnmatch#module-fnmatch
import fnmatch
# Create Path() instance with path to text file (can be reference)
txt_file = Path(r"names.txt")
# Gather input
uname = input("Please enter the name you want to find: ")
# Set initial line variable
line = 0
find_all = False
# Use context maangement to auto-close file once complete.
with txt_file.open() as f:
for line in f.readlines():
# If python 3.8, you can use assignment operator (:=)
if match_list := fnmatch.filter(line, uname) is not None: # Doe not match substring.
number_of_names = len(match_list)
name_index = [i for i, element in enumerate(line.split()) for word in match_list if word == element]
print(f"""
{number_of_names} name{"s" if number_of_names > 0 else ""} found on line {line} at position {name_index}.
""".strip())
line += 1
Edited to include fnmatch per some other comments in this thread about matching the full string vs. a substring.
You could try something like this:
import re
search_name = input("Enter the name to find: ")
with open("names.txt", "r") as f:
for line, row in enumerate(f.read().splitlines()):
if re.findall('\\b'+search_name+'\\b', row, flags=re.IGNORECASE):
print('Name "{0}" found in line {1}'.format(search_name, line))
You can remove the flags=re.IGNORECASE flag in case you want the seaarch to be case-sensetive.

How do you fix this for loop to validate a username?

This is for my GCSE coursework and I can't figure out what I have done wrong in the code.
I have tried changing the type of CSV file opening (changing it from w to r to r+) but the for loop is not being executed.
It is supposed to check if the username is in the CSV file and if it is, it should be accepted, else, they should be able to re-enter.
The usernames in the CSV files are Test01 and Test02
Here is my code:
import csv
import random
Player1 = 0
Player2 = 0
Again = True
File = open("Dice Game.csv","r+")
File.write("Test01" + "\n")
File.write("Test02" + "\n")
while Again == True:
Input1 = str(input("Player 1, please input your username."))
Open = open("Dice Game.csv", "r")
File = csv.reader(File)
for row in File:
User = row[0]
if User == Input1:
print("That username is not authourised, please re-enter.")
Again = True
break
else:
Again = False
Your immediate problem is having your logic backward:
if User == Input1:
print("That username is not authourised, please re-enter.")
If the user name matches, the user is authorized! Switch to != here and move the break.
Try this . . . I suggest you get familiar using with statement, I noticed you don't close your files
import csv
import random
with open('DiceGame.csv', 'w', newline='') as file:
writer = csv.writer(file, delimiter=",")
writer.writerow(['Test01', 'Test02'])
again = True
while(again):
_input = str(input("Player 1, please enter your username: "))
with open("DiceGame.csv", 'r') as file:
reader = csv.reader(file)
for row in reader:
if _input in row:
# Username is valid
again = False
break
else:
print("Invalid username, please try again.")

Change text in file with Python

def false_to_true():
name = input("Input name: ")
file=open("users.txt","r")
lines = file.readlines()
file.close()
for line in lines:
username, lel, type = line.split("/")
while name == username:
name = input("input name again: ")
tip = True
with open("users.txt", "w") as users:
users.write(str(red))
#
#I do not know how to perform a given modification and enrollment into place in #the text.
#
#I wont to change word False to True for username i input.
#I have this text in file users:
#Marko123/male/False
#Mimi007/female/False
#John33/male/False
#Lisa12/female/False
#Inna23/female/False
#Alisa27/female/False
I won't to change word False to True for username I input.
I have this text in file users:
Marko123/male/False
Mimi007/female/False
John33/male/False
Lisa12/female/False
Inna23/female/False
Alisa27/female/False
You can just use the csv library and forget about string manipulation:
import csv
def false_to_true():
#read from user.txt file into list(data)
with open('users.txt', 'r') as userfile:
data = [row for row in csv.reader(userfile,
delimiter="/",
quoting=csv.QUOTE_NONE)]
while True:
#waiting for input until you enter nothing and hit return
username = input("input name: ")
if len(username) == 0:
break
#look for match in the data list
for row in data:
if username in row:
#change false to true
row[2] = True
#assuming each username is uniqe break out this for loop
break
#write all the changes back to user.txt
with open('users.txt', 'w', newline='\n') as userfile:
dataWriter = csv.writer(userfile,
delimiter="/",
quoting=csv.QUOTE_NONE)
for row in data:
dataWriter.writerow(row)
if __name__ == '__main__':
false_to_true()
Open the input and output files, make a set out of the user-input names (terminated by a blank line), then create a generator for strings of the proper format that check for membership in the user-input names, then write these lines to the output file:
with open('names.txt') as f, open('result.txt', 'w') as out:
names = {name for name in iter(input, '')}
f = ('{}/{}/{}'.format(a,b,'True\n' if a in names else c) for a,b,c in (line.split('/') for line in f))
output.writelines(f)
To modify a text file inplace, you could use fileinput module:
#!/usr/bin/env python3
import fileinput
username = input('Enter username: ').strip()
with fileinput.FileInput("users.txt", inplace=True, backup='.bak') as file:
for line in file:
if line.startswith(username + "/"):
line = line.replace("/False", "/True")
print(line, end='')
See How to search and replace text in a file using Python?
Ask for name and iterate throw your lines to check for username, like this:
def false_to_true():
name = input("Input name: ")
file=open("users.txt","r")
lines = file.readlines()
file.close()
users = open("users.txt", "w")
for line in lines:
username, lel, type = line.split("/")
if name == username:
type = 'True\n'# \n for new line type ends with '\n'
users.write("/".join([username, lel, type]))
users.close()
false_to_true()

Searching Python Dictionary by key value is returning multiple, consecutive results, not just 1

I am relatively new to Python and I am having trouble with the following.
I am trying to write a program that would read a CSV file of personal information and then display an individuals information based on entering an ID number.
It is almost working perfectly, except that when I search by id number, it is returning all of the results (rows) preceding the desired result, in addition to the result I want.
I am reading a CSV file into a dictionary. I am then naming the fields dynamically from the file based on the names from the CSV (theoretically the CSV file can contain 2 columns of data or 100, as long as there is one field named "id").
csvfile.txt looks like:
id,name,age
1,jay,35
2,jen,36
3,sam,38
4,mike,26
What I want is when I search for id "1", it returns:
"
id: 1
name: Jay
age: 35
"
...and it does.... but if I search for id "3", I am getting:
"
id: 1
name: Jay
age: 35
id: 2
name: Jen
age: 36
id: 3
name: Sam
age: 38
"
I can't figure out why it is not just returning the one row I am asking for... here is the core of the code:
def runprogram():
import csv
file = open(csvfile.txt, "r") #open my test file
reader = csv.DictReader(file, skipinitialspace=True, dialect='excel', delimiter=',')
totalfields = (len(reader.fieldnames)) #count all the fields in the files for the purpose of for looping.
result={} #new dictionary named result
resultfields = ""
i=1
for row in reader:
for i in range(1,totalfields):
resultfields = resultfields + reader.fieldnames[i] + ": " + row[reader.fieldnames[i]] + "\n"
i+1
result[row['id']] = resultfields #storing each line from the CSV into the results dictionary under the key "id"
#this was just some code so I could exit my program by typing "exit" in the input box...
idvalue=""
while idvalue != "exit":
#display the box in which to enter a id number
if idvalue =="":
message = "Enter id Number"
else:
message = result[idvalue]
#using easyGUI for my input and display boxes.
idvalue = eg.enterbox(msg=message,title='Print Results', default='', strip=True)
if idvalue:
identered = "1"#this was used for testing.
printresults(results[idvalue]) #call printresults function
else:
programmenu()
if idvalue =="exit":
exit()
def printresults(results):
output = "Information Requested:\n" + results
print(output)
Any help would be greatly appreciated!
You need to re-initialize resultfields for each row you process.
#!/usr/bin/python
import csv
def printresults(results):
print ("Information Requested:\n" + results)
file = open("/tmp/csvfile.txt", "r")
reader = csv.DictReader(file, skipinitialspace=True, dialect='excel', delimiter=',')
totalfields = (len(reader.fieldnames))
result={}
for row in reader:
resultfields = ""
for i in range(1,totalfields):
resultfields = resultfields + reader.fieldnames[i] + ": " + row[reader.fieldnames[i]] + "\n"
result[row['id']] = resultfields
idvalues = ["exit", "4"]
while 1:
idvalue = idvalues.pop() #eg.enterbox(msg=message,title='Print Results', default='', strip=True)
if idvalue == "":
message = "Enter id Number"
elif idvalue =="exit":
print "done"
exit()
else:
message = result[idvalue]
print(message)
Output now looks like:
name: mike
age: 26
done

Categories

Resources