在python中将websocket客户端用作类

在python中将websocket客户端用作类,python,class,websocket,Python,Class,Websocket,我试图使用websockets访问一些数据,但我无法真正绕过websockets文档中给出的示例 我有这段代码()并希望将其转换为一个类 import websocket import thread import time def on_message(ws, message): print message def on_error(ws, error): print error def on_close(ws): print "### closed ###" d

我试图使用websockets访问一些数据,但我无法真正绕过websockets文档中给出的示例

我有这段代码()并希望将其转换为一个类

import websocket
import thread
import time

def on_message(ws, message):
    print message

def on_error(ws, error):
    print error

def on_close(ws):
    print "### closed ###"

def on_open(ws):
    def run(*args):
        for i in range(3):
            time.sleep(1)
            ws.send("Hello %d" % i)
        time.sleep(1)
        ws.close()
        print "thread terminating..."
    thread.start_new_thread(run, ())


if __name__ == "__main__":
    websocket.enableTrace(True)
    ws = websocket.WebSocketApp("ws://echo.websocket.org/",
                                on_message = on_message,
                                on_error = on_error,
                                on_close = on_close)
    ws.on_open = on_open

    ws.run_forever()
其想法是在一个类中包含所有websocket功能,这样我就可以创建该类的一个对象

我试着开始做,但我甚至无法通过:

class MySocket(object):
    def __init__(self):
        websocket.enableTrace(True)
        self.ws = websocket.WebSocketApp("ws://echo.websocket.org:12300/foo",
                                    on_message = on_message,
                                    on_error = on_error,
                                    on_close = on_close)

    def on_message(ws, message):
        print message

    def on_error(ws, error):
        print error

    def on_close(ws):
        print "### closed ###"

    def on_open(ws):
    ws.send("Hello %d" % i)
错误立即从消息上的
开始,表示这是一个“未解析的引用”。

您需要在类方法中添加“self”:

class MySocket(object):
    def __init__(self):
        websocket.enableTrace(True)
        self.ws = websocket.WebSocketApp("ws://echo.websocket.org:12300/foo",
                                on_message = self.on_message,
                                on_error = self.on_error,
                                on_close = self.on_close)

    def on_message(self, ws, message):
        print message

    def on_error(self, ws, error):
        print error

    def on_close(self, ws):
        print "### closed ###"

    def on_open(self, ws):
        ws.send("Hello %d" % i)

WebSocketApp
的回调需要可调用对象(您在构造函数中传递的对象,如消息上的
,以及您在打开消息后设置的对象)

普通函数是可调用的对象,因此非OO版本工作正常,因为您正在传递普通函数

绑定方法也是可调用的对象。但是您的OO版本不是传递绑定方法。顾名思义,绑定方法绑定到对象。您可以使用
obj.method
表示法来实现这一点。在您的情况下,这就是self.on_message

self.ws = websocket.WebSocketApp("ws://echo.websocket.org/",
                                 on_message = self.on_message,
                                 on_error = self.on_error,
                                 on_close = self.on_close)
self.ws.on_open = self.on_open
然而,你还有另一个问题。虽然这将使您的错误消失,但它不会使您的代码实际工作。常规方法必须将
self
作为其第一个参数:

def on_message(self, ws, message):
    print message
同样值得注意的是,您并没有真正地将类用于任何用途。如果您从未从
self
访问过任何内容,则该类的行为就像一个名称空间。并不是说这总是一件坏事,但这通常是一个信号,表明您至少需要仔细考虑您的设计。你真的需要保持什么状态吗?如果不是,你为什么首先要上课


您可能需要重新阅读以了解方法,
self
,等等。

self将这些方法作为类方法,使这一方法正常工作,因为如果self调用on_error/message/close methods签名将得到满足,因为它将引用类本身

 class MySocket(object):
   def __init__(self,x):
     websocket.enableTrace(True)
     ## Only Keep the object Initialisation here  
     self.x=x
     self.ws=None

     # call This method from a Object and it will create and run the websocket 
    def ws_comm(self):
        self.ws = websocket.WebSocketApp(self.WS_URL,on_message = 
        self.on_message,on_error =self.on_error,on_close = self.on_close)
        self.ws.on_open = self.on_open
        self.ws.run_forever()

    def on_error(self,ws, error):
        print "onError", error

    def on_close(self,ws):
       print "onClosed"

    #Send some message on open 
    def on_open(self,ws):
       self.ws.send(json.dumps(register_msg))

    def on_message(self,ws, msg):
       self.ws.send(json.dumps(msg))


 user1=Userapp('x')
 user1.ws_comm()

我想这样做:

class FooClient(object):
    def __init__(self):
        def on_message(ws, message):
            print message
            # use 'self' variable to access other resource
            # handle message from websocket server like this
            self.handler.handle(message)

        def on_error(ws, error):
            print error

        def on_close(ws):
            print "### closed ###"

        def on_open(ws):
            ws.send("Hello %d" % i)

        # assign to 'self.handler'
        self.handler = FooHandler()
        # maybe there are another module should be initiated
        # ...

        websocket.enableTrace(True)
        self.ws = websocket.WebSocketApp("ws://echo.websocket.org:12300/foo",
                                         on_message = on_message,
                                         on_error = on_error,
                                         on_close = on_close)

    def run_forever(self):
        self.ws.run_forever()

    def close(self):
        """clean other resources"""
        pass
在方法
\uu init\uu(self)
中使用内部函数可以避免消息(self,ws,message)
方法上
的参数数量与
WebSocketApp
在消息上为其参数
提供的参数数量不匹配的问题(类方法还有一个参数
self

我有一个上面的
处理程序来处理消息,方法
关闭(self)
来清理一些资源,如果有的话,
永远运行(self)
来运行websocket。

这是有效的:

class MySocket(object):
    def __init__(self):
        websocket.enableTrace(True)
        self.ws = websocket.WebSocketApp("ws://echo.websocket.org:12300/foo",
                                on_message = self.on_message,
                                on_error = self.on_error,
                                on_close = self.on_close)

    @staticmethod
    def on_message(ws, message):
        print message

    @staticmethod
    def on_error(ws, error):
        print error

    @staticmethod
    def on_close(ws):
        print "### closed ###"

    @staticmethod
    def on_open(ws):
        ws.send("Hello %d" % i)

但是您无权访问self

将调用打包到匿名
lambda
函数中,以使用正确的
self
实现正确的调用:

class Client:
    def __init__(self, db, symbols):
        self.ws = websocket.WebSocketApp("wss://the.server.com/api",
                    on_message = lambda ws,msg: self.on_message(ws, msg),
                    on_error   = lambda ws,msg: self.on_error(ws, msg),
                    on_close   = lambda ws:     self.on_close(ws),
                    on_open    = lambda ws:     self.on_open(ws))

    def on_message(self, ws, message):
            msg = json.loads(message)
            print(msg)
    ...
我想知道为什么每个人都还在使用
ws
参数

读取错误日志

文件“venv/lib/python3.7/site packages/websocket/_app.py”,第343行,在_回调中 回调(*args)

查看我们的回调,
on\u open(self,ws)

当执行
try
块时,它检查回调是方法还是函数。 如果它是一个方法,它将执行
回调(*args)
来自
CustomClient的self已经作为参数在(*args)中传递。请注意,它在
def\u回调(self,callback,*args)
中已经有了自己的
self

因此,作为
CustomClient
实例的每个回调都不应该有ws参数。

只是更新其他作者在此页面上编写的代码,这对我来说很有用。 问题在于,在事件回调函数定义(如on_message)中,我们不应该使用ws作为参数。self会处理它,在这些事件处理函数的主体中,我们应该使用self.ws

class MySocket(object):
    def __init__(self):
        websocket.enableTrace(True)
        self.ws = websocket.WebSocketApp("ws://echo.websocket.org:12300/foo",
                                on_message = self.on_message,
                                on_error = self.on_error,
                                on_close = self.on_close)

    
    def on_message(self, message):
        # if you want to send something use like this
        # self.ws.send()
        print message

    def on_error(self, error):
        print error

    def on_close(self):
        print "### closed ###"

    def on_open(self):
        self.ws.send("Hello Message")

嗯,我不能让它像那样工作。我尝试:ws=MySocket();ws.run_ever();我得到一个错误:“MySocket”对象没有“永远运行”属性。但也许你是对的,我应该把它放在一个类中。@jbssm:好吧,你定义了一个类
MySocket
,它没有
run\u forever()
方法。您创建该类的一个实例,并尝试对其调用
run\u forever()
。你预计会发生什么?如果希望类自动将所有未知方法委托给
self.ws
,可以这样做,但需要为此编写代码。谢谢。我将停止使用该类,并尝试使用普通函数。我不是那样工作的。我尝试:ws=MySocket();ws.run_ever();我得到的错误是:“MySocket”对象没有“永远运行”属性。ws不是WebSocketApp对象。它是一个MySocket对象。您需要在对象中添加代码来启动它,或者只需在属性上调用run_forever,如:ws.ws.run_forever()谢谢。我想我只是不理解这背后的原则。现在我将停止使用这些类,只使用普通函数。请描述您需要的解决方案provided@DineshGhule我添加了一些描述,如果其中有错误,请发表评论。这似乎是解决问题的正确方法。如果没有lambdas,
on_message=self.on_message,on_error=self.on_error,…
@gil9red没有lambdas,你就失去了
self
。换句话说,在
on_消息中,
self
不会指向对象的实例。非常感谢。节省我几个小时。我已尝试使用lambda和self.on_消息,但我仍然收到
on_open()缺少1个必需的位置参数:“ws”
谢谢man@vc74。我都不记得我什么时候回答的了。不过这很有道理。
    def _callback(self, callback, *args):
    if callback:
        try:
            if inspect.ismethod(callback):
                callback(*args)
            else:
                callback(self, *args)

        except Exception as e:
            _logging.error("error from callback {}: {}".format(callback, e))
            if _logging.isEnabledForDebug():
                _, _, tb = sys.exc_info()
                traceback.print_tb(tb)
class MySocket(object):
    def __init__(self):
        websocket.enableTrace(True)
        self.ws = websocket.WebSocketApp("ws://echo.websocket.org:12300/foo",
                                on_message = self.on_message,
                                on_error = self.on_error,
                                on_close = self.on_close)

    
    def on_message(self, message):
        # if you want to send something use like this
        # self.ws.send()
        print message

    def on_error(self, error):
        print error

    def on_close(self):
        print "### closed ###"

    def on_open(self):
        self.ws.send("Hello Message")