Im doing something wrong here (python)

I’m working on a scouting gui and framework for my team. I have the following files (in a spoiler):
[spoiler]
teamLib.py:

#!/usr/bin/python

import os

toCommit = list()

class team:
    """
    Its a object to hold team data
    """
    def __init__(self, name = "", number = 0, robotName = "", robotType = 0):
        self.name = name
        self.number = number
        self.robotName = robotName
        self.robotType = robotType

def newTeam(name, number, robotName, robotType):
    """
    Wrote this before i found out about constructors, does the same thing as team.__init__()
    """
    temp = team()
    temp.number = number
    temp.name = name
    temp.robotName = robotName
    temp.robotType = robotType

    return temp

def teamFromDict(theDict):
    """
    Returns a team object based on a dictionary argument
    """
    return team(
        theDict"name"], 
        theDict"number"], 
        theDict"robotName"], 
        theDict"robotType"]
    )

def saveTeam(team_obj):
    """
    Appends the team object to the toCommit List
    """
    config = {}
    config"name"] = team_obj.name
    config"teamNumber"] = team_obj.number
    config"robotName"] = team_obj.robotName
    config"robotType"] = team_obj.robotType

    toCommit.append(config)
#    f = open("./Scouting/robot", "w+")
#    f.write(repr(config))
#    f.close()

def read():
    """
    Opens the config file, returns the superDict
    """
    try:
        f = open("./Scouting/robot", 'rt')
        try:
            content = f.read()
            config = eval(content)
            f.close()
            toCommit.insert(999,config)
            
        except:
            print "cannot read file"
    except:
        print "cannot open file"

def commit():
    """
    Writes the team values to the config file in a listed dict
    """
    f = open("./Scouting/robot", "w+")
    f.write(repr(toCommit))
    f.close()
    clearList(toCommit)

def clearList(lists):
    """
    A clever hack to kill a list
    """
    while True:
        try:
            lists.pop()
        except:
            break

def interpretList(lists, value):
    """
    Give it the list you want, and the position of the team, and it will return a team object with the dict data
    """
    return teamFromDict(lists[value])

def countListElements(lists):
    i = 0
    while True:
        try:
            lists*
        except:
            break
        i = i + 1
    return i

cmdlinehelpers.py:

import teamLib

numberOfTeamsInList = teamLib.countListElements(teamLib.toCommit)

def addTeam():
	teamLib.saveTeam(
		teamLib.team(
			raw_input("Team Name: "), 
			input("Team Number: "), 
			raw_input("Robot Name: "), 
			input("Robot Type: ")
		)
	)
	print "Saved to list"
	
def showTeam():
	print numberOfTeamsInList
	temp = numberOfTeamsInList
	request = input("choose a number")
	prettyify(teamLib.interpretList(teamLib.toCommit, request))

def prettyify(teamObject):
	print "Team Name: %d" %teamObject.name
	print "Team Number: %d" %teamObject.number
	print "Robot Name: %d" %teamOcject.robotName

and, finally, cmdLineTest.py:

#!/usr/bin/python

import teamLib, cmdlinehelpers

teamLib.read()

alive = True

numberOfTeamsInList = teamLib.countListElements(teamLib.toCommit)

print "There are the following number of teams in the list"
print numberOfTeamsInList

print "
Please enter your command:"

while alive:
	request = raw_input("$> ")
	if request == "show":
		cmdlinehelpers.showTeam()
	if request == "add":
		cmdlinehelpers.addTeam()
	if request == "help":
		print "Commands are: 

show, add, save, load, help, quit"
	if request == "save":
		teamLib.commit()
		teamLib.read()
		numberOfTeamsInList = teamLib.countListElements(teamLib.toCommit)
		print "Saved :D"
	if request == "load":
		teamLib.read()
		numberOfTeamsInList = teamLib.countListElements(teamLib.toCommit)
		print "Found %d teams" %numberOfTeamsInList
	if request == "quit":
		print "bye"
		alive = False


[/spoiler]
the problem is that when I call teamLib.read(), teamLib.toCommit, which is a list, inserts the contents of ./Scouting/robot (which is a list of dicts) into another list, or (for clarity’s sake) I get this:

{"teamName": 'YouBots'}]]

instead of:

{"teamName": 'YouBots'}]

any tips?*

If that’s consistently the problem, try doing a simple

teamLib.toCommit = teamLib.toCommit[0]

That might fix up the problem.

What does your “./Scouting/Robot” file look like normally? It’s hard to just read your code and provide feedback without seeing the data format.

Also, have you looked at “pickling” your data instead of using eval and repr? Pickled data should be faster to load and more secure than eval (which is a giant security hole…). And easier to get working.

I wasn’t able to spot the problem exactly, but try to check your objects’ values (print them to the interactive shell) just before/after you repr/eval them, and try to see if there was some sort of mistake in there.

Aside from that, here are a couple of tips you might wanna’ use to better you program’s performance a bit, and make it easier to use:

Enums:
You have yet to represent the type of robot in your outputs, such as prettyfiy(), but I already see that you defined the member robotType as a numeric one, so just in case you’ll want to represnt the robot’s type in text and not in numbers, you could use enums for that:

Taken from http://stackoverflow.com/questions/36932/whats-the-best-way-to-implement-an-enum-in-python

def enum(**enums):
return type(‘Enum’, (), enums)

Used like so:

>>> Numbers = enum(ONE=1, TWO=2, THREE='three')
>>> Numbers.ONE
1
>>> Numbers.TWO
2
>>> Numbers.THREE
'three'

You can also easily support automatic enumeration with something like this:

def enum(*sequential, **named):
    enums = dict(zip(sequential, range(len(sequential))), **named)
    return type('Enum', (), enums)

Used like so:

Numbers = enum(‘ZERO’, ‘ONE’, ‘TWO’)
Numbers.ZERO
0
Numbers.ONE
1

Len(object):

The Len method is used to get the length of an object holding a collection. e.g, a string can be a collection (a collection of single strings or “chars” appended).
You could use it to return the count of items in your list, like this:

def countListElements(lists):
    return len(lists)
    # if you use this method only for the toCommit list, do it like this:
    # return len(self.toCommit)

Keep us updated on how the program is progressing. :slight_smile:

here is ./Scouting/robot: (whitespaced in json-like format for your readability)

{
    'robotName': 'The lord', 
    'robotType': 2, 
    'name': 'Bacon Scouts', 
    'teamNumber': 1233
}, 
{
    'robotName': "CheeseLord", 
    'robotType': 2, 
    'name': "The Guys", 
    'teamNumber': 2345
}

That’s your issue. (assuming I’m internally evaluating that correctly…) Python is going to interpret that as an array, and then you are inserting that array into a list. Hence your double packed list.

I’d highly recommend learning how pickling works. It’s very easy and better than using eval in that location.


#!/usr/bin/python
import pickle

filename = "p.txt"

f = open(filename, "w")
pickle.dump({1:"a", 2:"b", 3:"c"}, f)
f.close()

f = open(filename, "r")
print pickle.load(f)
f.close()

You could also edit the code to instead use += instead of append. That’ll solve your problem as well, but still leaves a security vulnerability.

how would you reccomend i proceed with as little security vulnerabilities as possible?

Web searches recommend JSON, which makes a lot of sense given how the format is put together. Use the cjson module or another similar module to parse JSON rather than eval as you have above. That will do sanity checks rather than blindly trust the code. I was going to recommend pickling until I started reading about the security of pickling. The format is designed for ease of use over security, sadly. It’s an interesting read if you are interested in that type of thing.

I am intending this to be a library that i can implement in many different ui’s (symbian was the origional target, but I am going to write a gtk+ ui for linux and a tkinter one if you really want me to), so i need a 100% python solution. I am most likely going to go with http://pypi.python.org/pypi/simplejson/ as the json parser.

Sounds reasonable.