Mokus
Mokus

Reputation: 10410

Dictionary in python

I'm creating a server-client communication, and I want to store some information in a dictionary, so I created a Global dictionary

global commandList
commandList = {}

And when a client is connection to the server I'm trying to store some information in the following way

self.clientname = str( self.client_address )
commandList[self.clientname]['lastcommand'] = GET_SETUP

but I'm getting the following error

commandList[self.clientname]['isready'] = False
KeyError: "('134.106.74.22', 49194)"

UPDATED:

This is a part of the code.

class MCRequestHandler( SocketServer.BaseRequestHandler ):

    global clientsLock, postbox, rxQueue, disconnect, isRunning, commandList
    postbox = {}    
    rxQueue = Queue.Queue()
    disconnect = {}
    commandList = {}
    clientsLock = threading.RLock()
    isRunning = {}


    def setup( self ):               
        clientsLock.acquire()        
        if len( postbox ) == 0:            
            self.clientname = 'MasterClient'
            postbox['MasterClient'] = Queue.Queue()            
            mess = str( self.client_address );            

            postbox['MasterClient'].put( self.createMessage( MASTER_CLIENT_CONNECTED, mess ) )
            print "Client name: %s" % str( self.clientname )  
            self.request.settimeout( 0.1 )                     
        else:            
            #Send message to the master client            
            self.clientname = str( self.client_address )               
            print "Client name:%s" % self.clientname

            postbox[self.clientname] = Queue.Queue()

            #Setting up the last command
            if not commandList.has_key( self.clientname ):
                commandList[self.clientname] = {}

            commandList[self.clientname]['lastcommand'] = GET_SETUP
            commandList[self.clientname]['isready'] = False            

            self.request.settimeout( COMMANDTABLE[commandList[self.clientname]['lastcommand']]['timeout'] )           

            self.transNr = 0;    
            self.start = True;
            isRunning[self.clientname] = True;

        disconnect[self.clientname] = True                   
        clientsLock.release() 

Upvotes: 0

Views: 5501

Answers (5)

tomasz
tomasz

Reputation: 13082

To solve the problem with KeyError, you have to create a nested dictionary first. There're two simple options:

import collections
commandList = collections.defaultdict(dict) 

or wiothout importing anything:

commandList.setdefault(self.clientname, {})['lastcommand'] = GET_SETUP

Depenending if your application is multithreaded or not, you could consider wrapping your dictionary with some class, so you pass the instance to threads instead of using global variable and probably adding some locking as you shouldn't relay on GIL. You could try to pass just a subdictionary to the clients as well.

Upvotes: 0

Richard
Richard

Reputation: 1690

Other people have already pointed out how to fix this problem, but perhaps not explained why. What you are trying to do is create values in a nested dictionary, or, in other words, a dictionary of dictionaries.

Thus your first dictionary is called commandList with keys of self.clientname. Each of the values in this dictionary is in fact a dictionary itself- or it should be.

You are never actually telling python that these values should be dictionaries, however, and so you are getting an error. As has been pointed out, from the code you've given, this should occur in the second snippet as well.

There are lots of ways to solve this, but the easiest would be to do something like:

if not commandlist.has_key(self.clientname):
    commandlist[self.clientname] = {} # Create an empty dictionary.

commandlist[self.clientname]['secondlevelkey'] = 'value'

You should perhaps be a little concerned that you are using global variables. I see that you are doing this as thread synchronisation, which is a bad idea because you are not doing any variable locking or access control to prevent dead/live locks and other synchronisation errors. Without knowing how you're using this command list, it is impossible to say how you should go about solving it.

If you give more information about the problem, we can probably advise how to solve it better.

Upvotes: 5

Mihai Maruseac
Mihai Maruseac

Reputation: 21460

I guess you have to do a two-step initialization

self.clientname = str( self.client_address )
commandList[self.clientname] = {}
commandList[self.clientname]['lastcommand'] = GET_SETUP

Try now.

Upvotes: 2

user2665694
user2665694

Reputation:

Are trying to insert a value into a nested directory without checking if the key for the first level exists...

if not self.clientname in commandList:
    commandList[self.clientname] = dict()

Upvotes: 0

Cat Plus Plus
Cat Plus Plus

Reputation: 130004

You're trying to read value that's not in the dict. Use defaultdict, or create commandList[self.clientname] first. Also try not to use global variables.

import collections
commandList = collections.defaultdict(dict)

Upvotes: 3

Related Questions