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 currentid
in the line:
del connections[currentid]
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). currentid
is 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:
del connections[self.currentid]
However, I don't think the rest of your code is doing what you think it is either. This line in the open
method:
currentid = global_counter
doesn't set the currentid
attribute of your SocketHandler
object. Assigning to a bare name always assigns to a local variable, unless you explicitly declare it global
(you appear to be aware of this, since you've used the global
keyword). So in the open
method, currentid
is a local function variable; its value is lost at the end of the open
method.
In fact, your SocketHandler
objects do not have a currentid
attribute at all (unless there's more code you haven't shown us). Putting currentid = 0
in the class block doesn't give all the SocketHandler
instances a currentid
attribute. It gives the SocketHandler
class itself an attribute currentid
; this is just as the def open(self):
block creates an open
attribute (storing a function) on the class object, not on each individual instance.
Reading self.currentid
in the on_close
method will fail to find a currentid
attribute in the object self
, so Python will look at the class of self
which is SocketHandler
. That object does have a currentid
value, so the result of reading self.currentid
will be 0
, whether or not you've previously run open
on that SocketHandler
.
If you meant to store the currentid
as an instance variable in each SocketHandler
, then the line in open
would need to be:
self.currentid = global_counter
This assigns to the currentid
attribute of the object referred to by self
. You would also then need to change all the other references to currentid
in your methods to self.currentid
.
currentid
should be self.currentid
since it is a class variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With