[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