0

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() 
2
  • 1
    The second code snippet should already create an exception. Please show more code. Commented Jul 19, 2011 at 7:54
  • @iUngi: If commandList = {} is done at the top-level of your program, you do not need to add global commandList. Commented Jul 19, 2011 at 7:57

5 Answers 5

5

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.

Sign up to request clarification or add additional context in comments.

1 Comment

the code snippet may be simplified: commandList.setdefault(self.clientname, {})['secondlevelkey'] = 'value'
3

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) 

2 Comments

I have 3 client, so I created three threads, and I'm using the dictionary to synchronize this clients. What is the other solution, without global variable?
@iUngi: If you're doing networking, look into Twisted. You most likely don't need threads at all.
2

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.

Comments

0

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() 

Comments

0

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.