Training, Open Source computer languages
PerlPHPPythonMySQLApache / TomcatTclRubyJavaC and C++LinuxCSS 
Search for:
Home Accessibility Courses Diary The Mouth Forum Resources Site Map About Us Contact
 
20.9.2014 - We have just updated our course layouts and descriptions and added our 2015 schedule.

Python key error

Posted by PaulStat (PaulStat), 6 October 2010
Ok so I have the following code, ReadMyData passes a tuple of dictionaries to InsertChannelPrograms, which then builds a values tuple and appends it to a list depending on how big the input tuple (listDict) was.

Code:
def ReadMyData(self,datFile):
  channelID = datFile[:-4]
  fields = ["PROGTITLE", "SUBTITLE",
             "EPISODE", "YEAR", "DIRECTOR",
             "PERFORMERS","PREMIERE", "FILM",
             "REPEAT", "SUBTITLES", "WIDESCREEN",
             "NEWSERIES","DEAFSIGNED", "BNW",
             "STARRATING", "CERTIFICATE", "GENRE",
             "DESCRIPTION","CHOICE", "DATE",
             "STARTTIME", "ENDTIME", "DURATION"]
  delim    = '~'
 
  lineReader   = csv.DictReader(open("./input/" + datFile,'rb'),
                 delimiter=delim,fieldnames=fields)
 
  # Read the header lines
  lineReader.next()
  lineReader.next()
 
  channelPrograms = []
 
  for row in lineReader:
     channelPrograms.append(row)
 
  for i in range(len(channelPrograms)):
     if (i+3) < len(channelPrograms):
        self.InsertChannelProgrammes(channelID,(channelPrograms[i],
        channelPrograms[i+1],channelPrograms[i+2],channelPrograms[i+3]))
     elif (i+2) < len(channelPrograms):
        self.InsertChannelProgrammes(channelID,(channelPrograms[i],
        channelPrograms[i+1],channelPrograms[i+2]))
     elif (i+1) < len(channelPrograms):
        self.InsertChannelProgrammes(channelID,(channelPrograms[i],
        channelPrograms[i+1]))
     else:
        self.InsertChannelProgrammes(channelID,(channelPrograms[i]))

def InsertChannelProgrammes(self,channelID,listDict):
  sqlString = """INSERT INTO CHANNELPROGRAMME(CHANNELID,DTE,STARTTIME) VALUES(%s,%s,%s)"""
  columns = []
  for i in range(len(listDict)):
     tempDict = listDict[i]
     valuesTuple = (channelID,self.FormatDate(tempDict["DATE"]),tempDict["STARTTIME"])
     columns.append(valuesTuple)
  if len(columns) > 0:
     self._cursor.executemany(sqlString,columns)



This code gives me the error

Quote:
Traceback (most recent call last):
 File "noThread.py", line 82, in <module>
   processing.ReadMyData(channelFile+'.dat')
 File "noThread.py", line 52, in ReadMyData
   self.InsertChannelProgrammes(channelID,(channelPrograms[i]))
 File "noThread.py", line 58, in InsertChannelProgrammes
   tempDict = listDict[i]
KeyError: 0


I simplified the concept to see if it would work and it does, see below:

Code:
>>> dateList = []
>>>
>>> dateDict1 = {'DATE': '2010-06-20'}
>>> dateDict2 = {'DATE': '2010-06-28'}
>>>
>>> dateList.append(dateDict1)
>>> dateList.append(dateDict2)
>>>
>>> def PassList():
...    TakeList((dateList[0],dateList[1]))
...
>>> def TakeList(listDict):
...    for i in range(len(listDict)):
...       tempDict = listDict[i]
...       print tempDict["DATE"]
...
>>> PassList()
2010-06-20
2010-06-28


So any ideas why I'm getting this?

Posted by dcorking (David Corking), 25 February 2011
Paul, You should be able to get more detail with the debugger.

Meanwhile, my guess is that the KeyError happens because (at the time of the traceback) listDict is not a list of dictionaries but a dictionary.

Take a look at this line
Code:
self.InsertChannelProgrammes(channelID,(channelPrograms[i]))

I made a quick demo program to illustrate my idea
Code:
#!/usr/bin/python

myDictCoats = { "tree" : "bark" , "dog" : "fur" }
myDictFrench = { "boy": "garcon", "fish": "poisson"}

myTupleOfDicts = (myDictCoats, myDictFrench)

i=0

print "This is when your program seems to work: two appended dictionaries"
# compare the next line to self.InsertChannelProgrammes(channelID,(channelPrograms[i], channelPrograms[i+1]))
good = (myTupleOfDicts [i], myTupleOfDicts [i+1])
print good
print ("This object has"), type(good), (" and length"), len(good)
print "Zeroth element is", good [i]
print

print "I suggest that this is the failure point: one dictionary"
# compare the next line to self.InsertChannelProgrammes(channelID,(channelPrograms[i]))
broken = (myTupleOfDicts [i])
print broken
print "This object has", type(broken), (" and length"), len(broken), "\n"
# As this is of type 'dictionary', not a tuple, print broken [i] will give KeyError: i

# A quick fix might be easy: add a comma
print "I added a comma to the assignment statement"
fixed = (myTupleOfDicts [i],)
print fixed
print ("This object has"), type(fixed), (" and length"), len(fixed)
print "Zeroth element is", fixed [i]

Sorry about all the repetition.
Run my demo with the debugger or the interpreter to play with it.

My output is Quote:
This is when your program seems to work: two appended dictionaries
({'tree': 'bark', 'dog': 'fur'}, {'boy': 'garcon', 'fish': 'poisson'})
This object has <type 'tuple'>  and length 2
Zeroth element is {'tree': 'bark', 'dog': 'fur'}

I suggest that this is the failure point: one dictionary
{'tree': 'bark', 'dog': 'fur'}
This object has <type 'dict'>  and length 2

I added a comma to the assignment statement
({'tree': 'bark', 'dog': 'fur'},)
This object has <type 'tuple'>  and length 1
Zeroth element is {'tree': 'bark', 'dog': 'fur'}

I think you might be able to fix your code if you add a comma near the end of line 52

If that doesn't help, you could try Graham's new forum, http://www.wellho.net/ask/



This page is a thread posted to the opentalk forum at www.opentalk.org.uk and archived here for reference. To jump to the archive index please follow this link.

You can Add a comment or ranking to this page

© WELL HOUSE CONSULTANTS LTD., 2014: Well House Manor • 48 Spa Road • Melksham, Wiltshire • United Kingdom • SN12 7NY
PH: 01144 1225 708225 • FAX: 01144 1225 899360 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho