First some background, i am writing a stats program for my school, the way you enter stats is by a window that has a textbox that shows how many of that stat the player has, lets say pass thrown, and two buttons a plus and a minus to add or subtract from that number. Now the way i am recording these stats is when the user clicks the plus button it opens up the stat file for the player and writes the stat name i.e. passes ans the number in the text box. My problem is when you go to write the stats information to the text file for the 20 plus stats they all get written on the first line each overwriting the one before it. So i need a way to write each stat on its own line.

Also as a side note this was the only way i could think to hold the stats information if there is a better way i would much like to know.

here is one of those definitions stated above:

begin = self.passes.GetValue()
        new = int(begin) + 1
        self.passes.SetValue(str(new))
        i = self.GetTitle()
        i.strip()
        file.close()
        file = open(i + '_stats.txt', 'a')
        file.writelines(str(new) + " passes" + "\n")
        file.close()

file.writelines(str(new) + " passes" + "\n")
expects a list as argument, use
file.write(str(new) + " passes" + "\n")
to write a string

Also, file is a function name in Python2, it would be better to use something like variable name fapp (for file append)

the problem is that every time you click the plus button it writes out every click. In this code segment:

begin = self.passes.GetValue()
        new = int(begin) + 1
        self.passes.SetValue(str(new))
        i = self.GetTitle()
        i.strip()
        file.close()
        file = open(i + '_stats.txt', 'a')
        file.write(str(new) + " passes" + "\n")
        file.close()

it gave this output:
1 passes
2 passes
3 passes

The output i want is:
(after one click)
1 passes
(after 2 clicks)
2 passes
(after 3 clicks)
3 passes

so the final output should be just:
3 passes

So you don't want to append to the file, you want to update its contents?

How many files are there? One per team? One per player? One per stat?

If the file is in ASCII form (like your sample stat was) and you need to update it, you will likely have to re-write the entire file every time you change anything. If the file is small enough and the data is all available, this isn't necessarily a bad implementation.

If the data is organized into fixed size records, you can perform partial file updates by calculating the position to seek() to and just writing the updated data. (Note that seek and open for append don't get along well together.)

there is one text file in the form of name_stats.txt but i was wondering of there was a better way of holding all of the stats for each player instead of a individual text file for 25+ players.

So your current data set is about 25 players with 20 statistics each?

Do you anticipate the number of players or the number of statistics to grow?

How critical is it that updates to the data be committed to disk immediately? (How bad would it be to 'lose' one or more updates?)

With your current data size, you could have an application that read the data, perform one or more updates to the data and then write the data as it exits normally. The primary drawback being the 'exits normally' phrase. If it did not exit normally, all of the updates from that run would be lost. It could be extended slightly to write the whole file every time any data changed as long as the target media (hard-drive?) was fast enough that it didn't hold you up from making the next update. Alternatively you could maintain a 'transaction file' with a list of the changes you make as you make them that is deleted after the whole file is written. It would contain data something like "Player 1's Stat 6 is now 12" though in practice the data in the file would likely be 1;6;12 . When your program starts up and reads the data file, it looks for the transaction file and performs any updates it finds. (If it finds any, I would write the file at that point and then delete the transaction file.)

It has the advantage that the file is probably simple, straight-forward and likely even human readable / editable if that were to be desired.

The file format might look something like one of the following:

Jack
12
13
14
15
.
.
.
Bob
23
1
6
13
.
.
.

Or a more compact form might look like:

Jack;12;13;14;15;...
Bob;23;1;6;13;...

I used a ';' to separate fields in the last example, but you could use any character not found in the other fields. Python has some nice methods to read and parse files in either format, but the second might actually be easier to read and parse. You would just read each line and split on the ';' and you have an array with the name in the first spot and the statistics in the rest of the spots. This format also lends itself to being imported into a spreadsheet if that might ever be useful.

You may have noticed that none of the forms put a label on each data item. I'm presuming that your code knows what they are and adding the additional labeling tends to bloat the output file quickly. The form above, if it might be used to import into a spreadsheet could be extended by adding a row of 'labels' as the first line of the file. You output the labels and delimit them like the data fields. When reading the file in, you skip (ignore) the first line.

If you find that re-writing the file takes too long the next step would be to put the data into a format that facilitates only writing part of the file at a time. (Though these type of changes move us away from the 'easy to import into a spreadsheet' format and would once again not include labels.)

If we extend slightly from the last form and set a few limits, we could develop a maximum length for each player. We could limit the name to 25 characters (is that enough?) and project that each of the stats would be no more than 6 characters (999999) (is that enough?) this would make a single players record 25 + 6 * 20 or about 145 characters, adding the delimiters there are 20 more characters making 165 and if we think we might need more space in the future we could allow for it now and say 200 characters (bytes) per player.

So if there was a way to write the player's records 200 bytes apart from each other they shouldn't ever overlap. (We might want to add some checking code to make sure we don't write too much, it would corrupt the following player.) Once the file was created, we can read and/or write each player individually. We use the file command seek() to position the file pointer to the start of the record and then read or write that record. To read or write the same record or another record we need to seek again.

Scaling the size back a little you might have something like:

#----+----+----+----+----+;----+-;----+-;----+-;----+-\n
#Jack;12;13;14;15\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#Bob;23;1;6;13\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

I made all of the lines python comments so we didn't get strange highlighting. The first line is the 'prototype record' it has 25 characters in the name, and 6 in each stat with delimiters and a newline. The remaining lines are the two records. Note that I didn't expand each field to fill all of its space (though that is an option if you like that better). You can continue to use a newline character as the 'end-of-record' mark or you could replace it with another character that isn't in the other data (and isn't the field separator). The X's represent filler characters to fill out the record to its target size.

This article has been dead for over six months. Start a new discussion instead.