I have a python application which is as follows:
global_counter = 0
connections = {}
class SocketHandler():
currentid = 0
def open(self):
global global_counter
global connections
currentid = global_counter
global_counter += 1
connections[currentid] = self
print "WebSocket " + str(currentid) + " opened"
def on_close(self):
global connections
print "WebSocket " + str(currentid) + " closed"
del connections[currentid]
I’m getting the error:
NameError: global name 'currentid' is not defined
on the lines of “open” and “on_close” where I print that I am opening/closing the connection. I defined it in the class, why is it not in scope. Also, I have read that using global variables is bad, but I don’t see a way around this. Can someone point out what I should do? Thanks.
You don’t have implicit access to attributes inside methods, in Python.
A bare name like
currentidin the line:always looks up a name in the local function scope, then in each enclosing function scope, before trying the global module scope (and then looks at built-ins as a last resort).
currentidis a class attribute, which won’t be found in any of those scopes.To look up an attribute in Python you always need to specify an object in which to look. Though the lookup protocol means the object need not necessarily have the attribute itself; attribute lookup will fall back to the class of the object you specified (and the base classes, if inheritance is involved).
So this would work:
However, I don’t think the rest of your code is doing what you think it is either. This line in the
openmethod:doesn’t set the
currentidattribute of yourSocketHandlerobject. Assigning to a bare name always assigns to a local variable, unless you explicitly declare itglobal(you appear to be aware of this, since you’ve used theglobalkeyword). So in theopenmethod,currentidis a local function variable; its value is lost at the end of theopenmethod.In fact, your
SocketHandlerobjects do not have acurrentidattribute at all (unless there’s more code you haven’t shown us). Puttingcurrentid = 0in the class block doesn’t give all theSocketHandlerinstances acurrentidattribute. It gives theSocketHandlerclass itself an attributecurrentid; this is just as thedef open(self):block creates anopenattribute (storing a function) on the class object, not on each individual instance.Reading
self.currentidin theon_closemethod will fail to find acurrentidattribute in the objectself, so Python will look at the class ofselfwhich isSocketHandler. That object does have acurrentidvalue, so the result of readingself.currentidwill be0, whether or not you’ve previously runopenon thatSocketHandler.If you meant to store the
currentidas an instance variable in eachSocketHandler, then the line inopenwould need to be:This assigns to the
currentidattribute of the object referred to byself. You would also then need to change all the other references tocurrentidin your methods toself.currentid.