I'm trying to figure out how to view a specific row in Python for example, I have a contact.csv file and I would like to view their name, email and phone number based on user input.
So, if a user inputs 2, for example, it would display contact 2's information.
Any help would be greatly appreciated,
Thanks.
If you’re just doing this one time, you can keep track of the line numbers:
def view_contacts():
contact_view = int(input("Number: "))
with open (FILENAME) as file:
for linenum, line in enumerate(file);
if linennum == contact_view-1;
print (line, end= "")
print ()
break
Notice that -1, because humans often count 1-based rather than 0-based like Python.
You can make this a little shorter:
def view_contacts():
contact_view = int(input("Number: "))
with open (FILENAME) as file:
for line in itertools.islice(contact_view-1, contact_view):
print (line, end= "")
print ()
But if you’re doing this over and over, you probably just want to read the whole file into memory so you can index it:
with open(FILENAME) as file:
contacts = list(file)
def view_contacts(contacts):
contact_view = int(input("Number: "))
print(contacts[contact_view], end="")
print ()
If the file is too big to read into memory, but looping over it repeatedly is too slow, you could look into linecache, or building your own cache, or consider converting the file into a format that you can index directly, or maybe just using a database that does that for you.
Related
I am trying to convert from string to float. I am pulling the text from a file. Any help or hints would be greatly accepted. I am a newbie on coding. Thanks in advance.
def main():
name =["","","","","",""]
lname = ["","","","","",""]
grade = [0,0,0,0,0]
#total = 0
#count = len(name)
#average = total / count
# for i in range(len(grade)):
# total += grade[i]
#Intro
print("Grades Processing App!\n")
infile = open("gradestest.txt", "r")
for n in range(5):
line = infile.readline()
#split data into 3 fields
name[n], lname[n], grade[n] = line.split(",")
grade[n] = float(grade[n])
#infile.close()
#Display data on screen
print("Name\t\t\tGrade")
print("--------------------")
for i in range(5):
print(name[i], "\t", lname[i], "\t", grade[i])
print('\n')
infile.close()
#for n in range(len(grade)):
#total += grade[n]
# count +1
# print(average)
print('Enter the following student information')
FirstName = input("\tFirst name: ")
LastName = input("\tLast name: ")
Grade = float(input("\tTest grade : "))
infile = open("gradestest.txt", "a")
infile.write(name + "," + lname + "," + float(grade) + "\n")
infile.close()
main()
The problem in your code you can't write float values to file. You can only write string value, you can convert it to float when reading the file.
def main():
print("Grades Processing App!\n")
with open('test.txt') as fp:
data = [line.strip().split(",") for line in fp]
#Display data on screen
print("Name\t\t\tGrade")
print("--------------------")
for name, lname, grade in data:
print(name, "\t", lname, "\t", grade)
grades_avg = sum([float(val[2]) for val in data])/len(data)
print("\nAverage:", grades_avg)
print('\nEnter the following student information')
fname = input("\tFirst name: ")
lname = input("\tLast name: ")
grade = input("\tTest grade : ")
with open("test.txt", "a") as fp:
fp.write(fname + "," + lname + "," + grade + "\n")
main()
Hmmm...so there is quite a bit to discuss I think.
1) First, we note that in python you don't need to allocate memory for your objects. Hence, declaring the size and content of your variables is unnecessary. Python is dynamic, hence one would simply say, "x=[]", to begin a list. and then "x.append(7)" to append a 7 to a list. If you are using ipython (highly recommended) then you can play around with variables on-the-fly and see what they do. For example x.(press tab) will show you all the "methods" available for lists.
2) There are many functions in python that simplify doing repeated tasks. For example, the join method for strings, inserts any string between the sequence of strings your provide. Another example is that open() automatically closes files if the variable isn't used anymore, hence in python you can normally open, read, and close a file in one line.
3) Python highly revolves around iterators that allow you to simplify many many tasks. These include builtins, like sorted, reversed, map, filter, range, etc. It is highly recommended to become familiar with those, as they will greatly enhance your code.
Lets simplify your code a bit:
# Read all lines at once. No need to say 'r', that is the default.
# The file closes automatically when the variable falls out of scope.
lines = open('gradestest.txt').readlines()
# Split each line. You can do it all at once in a list comprehension.
lines = [line.split(',') for line in lines]
# Leaves all the entries alone but the last one. Python can access backwards.
# The line[:-1] means to access everything but the last item as a list.
# The line[-1] means to access the last item (which is grade).
lines = [line[:-1]+[float(line[-1])] for line in lines]
# There are other ways to read your file as well (probably faster).
# Python has a huge library of modules, like the csv module which is for
# opening and reading csv files.
# The join method inserts strings between other strings. The map function
# takes each item in an object and applies the given function to them. Hence,
# map(str,line) turned all the items into a string (including the item you
# made a float earlier.
print("Grades Processing App!\n")
print("Name\t\t\tGrade")
print("--------------------")
print('\n'.join('\t'.join(map(str,line)) for line in lines))
# Not quite sure what this code was for. You don't use your variables
# anywhere. Also you run float(grade) which I think will error, since
# grade is a list. Anyway, I think you meant to append to the file
# some new inputs.
print('Enter the following student information')
FirstName = input("\tFirst name: ")
LastName = input("\tLast name: ")
Grade = float(input("\tTest grade: "))
open('gradestest.txt','a').write(','.join([FirstName,LastName,Grade])+'\n')
Don't think I answered the original question. If you want to find an average in python, there are two builtin commands len() and sum() which count the number of items in a list and add up the items in a list. For example,
grades = [1,2,3,4,5]
average = sum(grades)/len(grades)
I know this is a lot more than you asked for, but since I left some long tips in the comments, I pasted them here with examples.
A tip about files: you can use with open('myfile.txt', 'r') as infile: and put the code that uses the file in that block under it. Once the execution of code leaves that block, the file is reliably closed - even in the case of an exception being thrown.
To address the question in your post, converting text to a float or int value is pretty simple. The only trouble is when the string data isn't in a format that can be converted to an int or float. The exception handling below will make your program a bit more robust and it won't blow up when the conversion fails. But looking at what you had in your code should work.
with open('gradestest.txt', 'r') as infile:
for line_no, line in enumerate(infile):
try:
name, lname, grade = line.split(',')
grade = float(grade)
except ValueError as ve:
print(f"Warning, file format incorrect on line "
f"{line_no + 1}: {ve}")
I added some fault tolerance to the loop that reads in grades. When .split() doesn't produce the right number of items, or float() fails trying to convert a non-numeric string, a ValueError is raised. The except block catches the ValueError and prints a warning about the file format, but the loop can continue to try and process the rest of the file.
Rather than have lists of data that rely on the index to associate different data with the same student, create a Student class that has data members for name and grade. That way you can iterate over the student list rather than iterating over a range of indices.
class Student:
def __init__(self, name, lname, grade=None):
self.name = name
self.lname = lname
self.grade = grade
The above isn't what some may consider a proper implementation of a class because we'll be accessing the data members directly from other code in your program. Since this is a very simple program that's just processing file data, and we only have three pieces of data to manage, we'll flex the coding standards a bit.
Now you have a way to reference grade and student data by attribute name on the student objects. And to be able to grab the list of students at different points in the program, we'll add them to a list.
student_list = []
with open('gradestest.txt', 'r') as infile:
for line_no, line in enumerate(infile):
try:
name, lname, grade = line.split(',')
grade = float(grade)
student_list.append( Student(name, lname, grade) )
except ValueError as ve:
print(f"Warning, file format incorrect on line "
f"{line_no + 1}: {ve}")
Then later in the program when we want to list out the students and their grades:
print(f"{'name':<20} Grade") # Pads 'name' to 20 characters with spaces.
for st in student_list:
print(f"{st.name+' '+st.lname:<20} {st.grade}")
I'm using f-strings to format the text. The text between curly braces is interpreted as Python code and returns strings at the positions in the string where they're at. The :<20 left-aligns and pads the text with spaces.
One last suggestion. This might be a little advanced, suppose you're maintaining student records and want to be able to save the information to a file, then come back to your program later and load your student objects back up with all their information in them, you could use the pickle module for that (although you might also consider a simple database - the sqlite module is pretty good)
Pandas is also a good option if you're working with tabulated student data - it can save its dataframes to file and retrieve them pretty easily.
Anyway, here's pickle:
import pickle
...
# Somewhere in your code...
save_file_y_n = input("Do you want to save student data? ")
if save_file_y_n.lower() in ['y', 'yes']:
file_name = input("Name of file: ")
# Write the Students out to a file.
pickle.dump(student_list, open(file_name, 'wb+'))
...
# Somewhere else in your code - or another script/program..
if load_file_y_n.lower() in ['y', 'yes']:
file_name = input("File name for student records: ")
# Reconstructs the Student objects from the file data
# with their name, lname, grades and any other attributes
# you may have added:
student_list = pickle.load(open(file_name, 'rb'))
print("List of students:")
for st in student_list:
print(f"st.name")
It's always a great idea to back your data up regularly in case the student data file gets somehow corrupted or accidentally deleted. You could even implement some code in your program to save student data in a new file each day and load the latest when the program starts.
A little information on this in case you're curious and not overwhelmed already https://wiki.python.org/moin/UsingPickle
Another option for saving application information is the json module. It can write basic data objects out to a file using plain text. https://docs.python.org/3/library/json.html
And of course you could use CSV (comma separated values) - there's a csv module for that, https://docs.python.org/3/library/csv.html?highlight=csv#module-csv.
Okay, So I´m doing a program that simulates dice rolls and then saves them to a file.
I thought that the easiest option, in my opinion, would be to just save every single iteration of the loop and save the print to the file line by line. But unfortunately, I cannot figure it out.
import random
output=[]
order=0
inpu_t=int(input("Enter the number of simulated throws: "))
f = open('file.txt','w')
figures = (0,)*6
for i in range(inpu_t):
order = order+1
throw = random.randint(1, 6)
figure = figures[throw -1]+1
print(order,'.throw and {}-times fell the number {}.'.format(figure, throw ))
output.append(order)
output.append(figure)
output.append(throw )
figures = figures[:throw -1]+(figure,)+figures[throw :]
print("\n")
with open('file.txt', 'w') as f:
for item in output:
f.write("%s" % item)
for i in range(6):
print('The number {} fell {}-times.'.format(i+1, figures[i]))
Secondly, I thought I could save all the variables to the list and then somehow through some function save it to a file.
output.append(order)
output.append(figure)
output.append(throw )
There I added all the data to the list.
with open('file.txt', 'w') as f:
for item in output:
f.write("%s" % item)
I added it to the file here.
My output in the file is this: "115216314412511"
I don't know how I should do it so that all 3 numbers are would be together in one line like in the code.
print(order,'.throw and {}-times fell the number {}.'.format(figure, throw ))
Append a Carriage Return "/r" with in the for loop after the append throw
hi the better way is to use logging instead to open each time file
read here : How to write to a file, using the logging Python module?
I have a file with data about students such as their name, address, grades, etc. I created a function that would delete a whole line from a text file based on a student's First Name and Last Name. This function worked correctly. However, afterward, I decided to update it so that if the user entered a name that was not in the file it would print: Student not found. However, now even, if the user types in a name that is in the file it still prints: student not found...
Here is my code:
def delete_a_record(filename):
x=input("Remove First Name:")
y=input("Remove Last Name:")
with open(filename, "r") as f:
lines = f.readlines()
with open(filename, "w") as f:
for i in lines:
t=i.split()
if t[0]!=x and t[1]!=y:
f.write(i)
elif x or y not in t:
print("Student Not Found")
f.close()
delete_a_record("mytextfile.txt")
Could someone explain to me why?
For what I undestood(correct me if I'm wrong), I guess there is two issues in your logic.
If you mean to test if both x and y are not in t you should test it separatelly, like:
if t[0]!=x and t[1]!=y:
f.write(i)
elif x not in t and y not in t:
print("Student Not Found")
The way it is now, if x is not None, the condition elif x or ... will always return true because x evaluates to True.
If you want to check if the student is not in the entire file, I think you should not be testing this for each line you read. Since you don't know in which line the student might be, maybe you could reorganize your code to process the whole file first before testing if the student was not found.
Probably because you are iterating line by line, so even if the name is in the .txt file every time the name doesn't match the current line it will print "Student Not Found". You need to rewrite you function so that the print statement is only made when the lines have been exhausted and the name has not been found.
If You Want to Use Your Function And Search In That (You Don't Want to Change Your Function) You Can Put Your Data In A List And Search In That List Like Below Code:
list=['f_Name = Lorem','l_Name = Ipsum']
if "f_Name = "+x in list or "l_Name = "+y in list:
print("True")
else:
print("Student Not Found")
I have tried to get help on this question all day, but none of the already-asked questions have solved my problem, and any answers I have asked to help me solve this problem have resulted in answers that didn't answer the question.
As it stands now, my program takes the values of MPG ratings represented in a CSV and puts them in a list. These lists represent maximum and minimum MPGs. Once the max/min MPG rating is found is where I get into my problem. I need to be able to print all the cars that have the minimum/maximum MPG value. Ideally, the models should be printed indented under the print statements for the maximum/minimum mileage ratings.
The way the CSV file is done the MPG ratings are in column 9 (index[8]). The make and models are in columns 2 and 3, respectively (index[1] and index[2], respectively). As you'll see in the code, I tried looping through the list and using an if statement to pull the make/model, but when I do that it does not work. I don't know if the files play a part or not, but any help would be appreciated.
# prints welcome screen, asks user what year they want vehicle data for, and asks user for file name to save vehicle data to
print("Welcome to EPA Mileage Calculator")
yearChoice = int(input("What year would you like to view data for? (2008 or 2009): "))
while yearChoice != 2008 and yearChoice != 2009:
print("Invalid input, please try again")
yearChoice = int(input("What year would you like to view data for? (2008 or 2009): "))
saveResults = input("Enter the filename to save results to: ")
def carData():
if yearChoice == 2008:
fileName = "epaVehicleData2008.csv"
elif yearChoice == 2009:
fileName = "epaVehicleData2009.csv"
fileIn = open(fileName, "r")
fileIn.readline()
minMPG = []
maxMPG = []
for line in fileIn:
line = line.strip()
dataList = line.split(",")
if dataList[0] not in ['VANS - PASSENGER TYPE', 'VANS - CARGO TYPE', 'TRUCK', 'MINIVAN - 4WD', 'MINIVAN - 2WD']:
minMPG.append(int(dataList[8]))
maxMPG.append(int(dataList[8]))
maximumMPG = max(maxMPG)
minimumMPG = min(minMPG)
fileOut = open(saveResults, "w")
print("EPA City MPG Calculator", "(" + str(yearChoice) + ")", file=fileOut)
print("---------------------------------", file=fileOut)
print("Maximum Mileage (city):", maximumMPG, file=fileOut)
for line in fileIn:
line = line.strip()
dataList = line.split(",")
if dataList[8] == maximumMPG:
print("\t", dataList[1], dataList[2], file=fileOut)
print("Minimum Mileage (city):", minimumMPG, file=fileOut)
for line in fileIn:
line = line.strip()
dataList = line.split(",")
if dataList[8] == minimumMPG:
print("\t", dataList[1], dataList[2], file=fileOut)
fileIn.close()
fileOut.close()
def complete():
print()
print("Operation Success! Mileage data has been saved to", saveResults)
print("Thanks, and have a great day!")
def main():
carData()
complete()
main()
You open the input file only once via:
fileIn = open(fileName, "r")
But then you attempt to iterate over the lines in the file three times using that same file handle. You have three of these:
for line in fileIn:
Since you never close and reopen the file, and you don't do anything to seek back to the beginning of the file, the second and third such iterations will never do anything, because you've already reached the end of the file. Using this construct does not cause the file pointer to be rewound and the contents of the file to be iterated over another time.
Since your interesting print statements are in the second and third iterations over the file, which won't produce any new lines (the code in those iteration blocks will never be called), of course your print statements are never called and no output is generated.
To fix your problem, if this is the only thing wrong with your code, just put this line before each of the second and third iterations over the file:
f.seek(0)
to seek back to the beginning of the file and iterate over the contents a second and third time.
To be more efficient, you could read each line once and store it in a list. Then you could iterate over the list each time, and not have to read from the file three times. You could even do the strip and the split just once, making the code even more efficient.
Another small logic error that I see is that you skip one line in your first iteration over the file. I assume that this is to skip a header row at the start of the file. But you don't do this for the second and third iterations, so it seems that if you only add the seek() as I suggested, you'll be trying to process the header line as a data line. This would also be solved by reading the file once into a list. You'd skip the first line of the file while you do this. If you want to leave the code alone other than adding the seek(), you should also skip the first line before the second and third iterations.
I am banging my head agaisnt a wall trying to figure out something that is simple.
Basically I have a .CSV with names in and test scores e.g.
Brad 4, 5, 7, 7
Dan 3, 6, 2, 7
What I want to do is write code that first all of prints out the tests scores. This bit works fine.
The aspect that I can not get to work is the part were the program reads the names, in the CSV. If the name is present it will append the CSV with the new score at the start. So insert the new value at array position 1.
If the name is not present in the CSV it will add name and then again insert the value at array position 1.
Here is the code that does not work currently, I don't believe it to be complicated however I must be thinking about it wrong.
import csv
def names():
global fn
fn = input("please enter first name \n").title()
namecheck = False
while namecheck == False:
nc = input("you have entered " + fn + " are you sure \n 1) Yes \n 2) No")
if nc == "1":
quiz()
namecheck = True
if nc =="2":
names()
def quiz():
option = input("do you want to print or append? \n 1) Print 2) Append")
if option =="1":
f = open('namelist.csv', 'r')
a = f.read()
print(a)
if option =="2":
score = input("please enter score")
score = int(score)
with open('namelist.csv', 'rt') as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
for field in row:
if field == fn:
XXXXXXXX <--- this is were I think I am going wrong.
names()
when you declare a def, you have to indent the entire section.
def quiz():
[-->INDENT HERE!] option = input("do you want to print or append? \n 1) Print 2) Append")
[-->INDENT HERE!] rest of def..
#back to main statements..
(Of course I don't mean for you to type "[-->INDENT HERE!]" literally)
Do you have to literally write to the file every time someone adds a new score or a new name? If writing to file at the end of program is an option, I'd suggest collecting all info ahead of time and then writing the data in bulk toward the end..that way you could maintain everything in memory and do the I/O with file in one go, sparing you a lot of file operations and giving you the convenience of working with python data structures such as dicts/sets etc....
If that's not an option...
Looking up names by reading the file is really inefficient as you are reading the entire file just to see if the name is present.
I'd recommend using a dict to store the list of names you've already entered. This way checking the dict to see if the name is present or not is much more efficient...You could try storing the dict with key=name and value=line number on which you entered the name while you wrote to csv.
That way if you found the name in dict, you can go to the particular line and then append your data like this:
Start reading and writing on specific line on CSV with Python
To insert an element in the first position (i am assuming this is after the name), you could do something like:
l = line.split(",")
#assumes first element is the name of the person
l.insert(1, new_score) # 1 is the position you want to insert the data
#then insert this data into a_NEW_CSV file, as writing to same CSV at same line is difficult...
See this for more details: Replace data in csv file using python