使用websocket客户端作为python中的类

时间:2014-11-17 20:03:57

标签: python class websocket

我尝试使用websockets访问一些数据,但我无法真正解决websockets文档中给出的示例。

我有这段代码(https://pypi.org/project/websocket_client/)并希望将其转换为类。

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)

错误立即开始在on_message中表示“未解决的参考”#34;

8 个答案:

答案 0 :(得分:7)

使用匿名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)
    ...

答案 1 :(得分:5)

WebSocketApp需要用于其回调的可调用对象(包括您在构造函数中传递的对象,如on_message,以及您在事后{i}重新设置的对象)。

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

绑定方法是也是可调用对象。但是你的OO版本并没有通过绑定方法。顾名思义,绑定方法绑定到对象。您可以使用on_open表示法执行此操作。就你而言,那是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 之外的任何内容,那么该类就像一个命名空间。并不是说这总是一件坏事,但它通常表明你需要至少考虑一下你的设计。你需要保持任何状态吗?如果没有,为什么你想要一个班级?

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

答案 2 :(得分:1)

你需要添加" 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)

答案 3 :(得分:1)

Self将这些方法作为Class方法,让这个方法工作,因为on_error / message / close方法签名将被self调用,因为它将引用类本身。

 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()

答案 4 :(得分:0)

我想尝试这种方式:

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

在方法__init__(self)中使用内部函数可以避免以下问题:on_message(self, ws, message)方法的参数数目与为其参数WebSocketApp提供的on_message数目不匹配(类方法还有一个参数self)。

我上面有一个handler来处理消息,方法close(self)用来清理一些资源,run_forever(self)是用来运行websocket的。

答案 5 :(得分:0)

这有效:

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)

但是你无法进入自我

答案 6 :(得分:0)

import websocket

try:
    import thread
except ImportError:
    import _thread as thread
import time


class OnyxGenericClient:
    """
    Onyx Client Interface

    """

    def __init__(self, ):
        websocket.enableTrace(True)
        ws = websocket.WebSocketApp("ws://localhost:3000/",
                                         on_message=self.on_message,
                                         on_error=self.on_error,
                                         on_close=self.on_close)
        self.ws = ws
        self.ws.on_open = self.on_open
        self.ws.run_forever()

    # def initiate(self):

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

    def on_error(self, error):
        return error

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

    def run(self, *args):
        global driver
        driver = True
        while driver:
            try:
                time.sleep(1)
                print("Say something nice")
                p = input()
                self.ws.send(p)
            except KeyboardInterrupt:
                driver = False
        time.sleep(1)
        self.ws.close()
        print("thread terminating...")

    def on_open(self):
        thread.start_new_thread(self.run, ())


if __name__ == "__main__":
    websocket.enableTrace(True)
    onyx_client = OnyxGenericClient()

我想知道为什么每个人仍然都使用ws参数。

读取错误日志。

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

    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)

看我们的回调on_open(self, ws)

执行try块时,它将检查我们的回调是方法还是函数。 如果它是一种方法,它将执行callback(*args)CustomClient中的我们自身已经作为参数传递给(* args)。请注意,它在self中已经有自己的def _callback(self, callback, *args)。 因此,每个CustomClient实例的回调都不应具有ws参数。

答案 7 :(得分:0)

只需更新此页面上其他作者编写的代码,即可为我工作。 问题在于,在事件回调函数定义(例如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")