Reputation: 11
I want the functions to be part of the class I am building, but I get an error There is probably a problem that the decorator function will be a function in the department. Is there a solution to the problem ? Thank you.
import engineio
class Websocket:
def __init__(self):
self.eio = engineio.Client()
self.eio.connect('http://localhost:5000')
self.eio.wait()
# get error in this function
@eio.on('connect')
def on_connect():
print('connection established')
Upvotes: 1
Views: 170
Reputation: 1121436
You can't use a decorator on a method where the decorator expression refers to an instance attribute. That's because decorators are executed when the function they decorate is being created. Inside a class
statement body that means that when decorators are applied, there is no class yet, and without a class, there can't be any instances either.
You have two options:
Just call self.eio.on('connect')
in the __init__
of your class, passing in a bound method:
class Websocket:
def __init__(self):
self.eio = engineio.Client()
self.eio.connect('http://localhost:5000')
self.eio.on('connect', self.on_connect)
# don't call wait, see below
def on_connect(self):
print('connection established')
This works because by the time __init__
is being called you have a class and an instance of that class (referenced by self
), and self.on_connect
returns a reference to a bound method (calling it will have self
passed in). @....
decorator syntax is just syntactic sugar, you don't have to use it. The engineio.Client.on()
method accepts the handler as a second argument, but you could also use self.eio.on('connect')(self.on_connect)
, which is a literal translation of what the decorator syntax does.
Use a nested function inside __init__
, and decorate that:
class Websocket:
def __init__(self):
self.eio = engineio.Client()
self.eio.connect('http://localhost:5000')
@self.eio.on('connect')
def on_connect():
print('connection established')
# don't call wait, see below
but that makes it much harder to use that function directly from other code.
Note that the engineio.Client.wait()
method blocks, it doesn't return, until the connection has ended. You would not normally put that kind of call in the __init__
method of a class!
Using a class to handle engineio
events is great, but don't start the client connection from the class. I'd do this instead:
class Websocket:
def __init__(self, socket_url):
self.eio = engineio.Client()
self.eio.connect(socket_url)
self.eio.on('connect', self.on_connect)
# other registrations
def on_connect(self):
# handle connection
# other handlers
def wait(self):
self.eio.wait()
websocket = Websocket('http://localhost:5000)
websocket.wait()
Upvotes: 3