[Tutor] Reading from files problem
Scottsa
pydevrsc at gmail.com
Mon Apr 20 04:36:21 CEST 2009
Hi Chris,
On Apr 19, 2009, at 5:45 PM, Chris Castillo wrote:
> I am trying to open a text file and read multiple lines containing the
> following:
>
> 745777686,Alam,Gaus,CIS,15,30,25,15,5,31,15,48,70,97
> 888209279,Anderson,Judy,Math Ed,14,30,30,13,11,30,16,18,58,72
This is CSV format data (comma separated values), and python has a
very nice library for reading it.
<http://docs.python.org/library/csv.html>
It does all of the heavy-lifting (file-handling) and splits the lines
into lists.
something like this:
import csv
studentReader = csv.reader(open('students.csv'), 'rb')
for student in studentReader:
student_values = do_something(student)
> I want to ask the user for the student number, check to see if that
> number is even valid and display something like:
.../snip/...
> totalpoints = 550
> hwgrades = float(hw1) + float(hw2) + float(hw3) + float(hw4) +
> float(hw5) + float(hw6) + float(hw7)
> testgrades = float(test1) + float(test2) + float(test3)
> studentpoints = float(hwgrades) + float(testgrades)
> avgrades = round(float(studentpoints / totalpoints) * 100.0, 2)
This could be done with the 'reduce' built-in library function,
combined with list slicing:
<http://docs.python.org/library/functions.html>
and
<http://www.diveintopython.org/native_data_types/lists.html>
hwgrades = reduce(lambda x, y: float(x) + float(y),
student_values[5:8])
... which translates into columns #6, #7 and #8 (remember, lists are
0=based)
You could write a simple method that does the reduction for you:
def reduce_numbers(number_list):
ret_val = 0.0
for val in number_list:
ret_val += float(val)
return ret_val
Then you'd call it like this:
some_result = reduce_numbers(student[5:8]
lamda defines a method, just like 'def' does, but does not name it
because it is used and disposed of immediately.
So, "do_something" could look like this (not tested or debugged):
def do_something(student_values, sought_id):
student_id = lines[0]
if sought_id == student_id:
last_name = lines[1]
first_name = lines[2]
major = lines[3]
hw_grades = reduce(lambda x, y: float(x) + float(y),
student_values[5:8])
test_grades = reduce(lambda x, y: float(x) + float(y),
student_values[8:10])
...[other code you may wish to perform]...
print first_name, last_name, identifier
Note: I didn't count the cols so my 'split' numbers are not correct,
but you get the idea.
You could even move the testing phase to the reading like this:
sought_id = 888209279 # however you are going to obtain this i.e.
from sys.argv or otherwise.
for student in studentReader:
if student[0] == sought_id:
doSomething(student)
Please also check-out string formatting here:
<http://docs.python.org/library/string.html>
It allows you to make prettier output if you like and find it easier
to read than a lot of string joins (val1 + val2 + ' - ' + val3... yuck!)
'%s, %s (%s): %0.2f points' % (last_name, first_name, student_id,
points)
'Doe, Jane (888209279): 76.22 points'
> That's what I have so far but I have a feeling I shouldn't use a for
> loop. I would really like any help trying to figure out this program.
> Thanks in advance.
If you are doing a lot of querying of the data, you could use sqlite
which would mean you iterate the file once into the database and you
can use sql to perform the lookup.
<http://souptonuts.sourceforge.net/readme_sqlite_tutorial.html>
You'd have to create the schema and use the student ID as the primary
key. You could also pre-process the values on import, so the results
would be pretty simple to obtain.
select student_name, test_grades, student_points, avg_grades from
studentdb where student_id = '888209279';
would return the values in a list. You could also perform searches by
last-name (all the "smith's", for example, or partial names or...
I realize that is a bit over what you were starting with, but it is
likely another logical step in your venture...
Okay, I hope this is clear enough to get you over a couple of points,
Scott
More information about the Tutor
mailing list