Reputation: 10410
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
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
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
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
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
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