代码之家  ›  专栏  ›  技术社区  ›  KiYugadgeter

如何在python中添加class属性?

  •  0
  • KiYugadgeter  · 技术社区  · 6 年前

    我想创建一个将数据从WebSocket传输到UDP套接字的类。
    此代码使用 simple-websocket-server 用于实现WebSocket服务器的模块。
    所以我试图添加UDP套接字作为类属性,但它会引发一个错误。 我怎么修?

    注意,我知道当dataWebSocket对象传递给simplesslWebSocketServer时,这个错误能够避免使用闭包。
    但我想尝试类嵌入UDP套接字,我想了解关于Python中的类属性。

    这是代码:

    from SimpleWebSocketServer import WebSocket, SimpleSSLWebSocketServer, SimpleWebSocketServer
    import multiprocessing
    from multiprocessing.managers import BaseManager
    import ssl
    import signal
    import sys
    import socket
    import os.path
    import traceback
    
    class DataWebSocket(WebSocket):
        def __new__(cls, cls_name, cls_bases, cls_dict):
            try:
                super().__new__(cls, cls_name, cls_bases, cls_dict)
                cls.udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # add udp socket as a class attribute (not instance attribute)
                cls.udp_sock.setblocking(False)
                cls.udp_sock.bind(("127.0.0.1", 6666))
                print("cls")
                return cls
            except:
                t, mes, tb = sys.exc_info()
                print(traceback.format_exception(t, mes, tb))
                return cls
        def __init__(self, server, sock, address):
            try:
                super().__init__(server, sock, address)
            except:
                t, mes, tb = sys.exc_info()
                print(traceback.format_exception(t, mes, tb))
        def handleMessage(self):
            try:
                if isinstance(self.data, str):
                    data = self.data.encode("utf-8")
                else:
                    data = self.data
                self.udp_sock.sendto(data, ("127.0.0.1", 7774))
                print("raw_data is:", self.data)
            except Exception as e:
                t, mes, tb = sys.exc_info()
                print(traceback.format_exception(t, mes, tb)) # just print error for keep it execute server.;
    
        def handleClose(self):
            print("connection: closed " + self.address)
            self.sendMessage("server exit")
            #sys.exit()
    
        def handleConnected(self):
            print("Connected", self.address)
    
    
    def start_data_receiver():
        #udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        #udp_sock.setblocking(False)
        #udp_sock.bind(("127.0.0.1", 6666))
        SSL = True
        if SSL:
            server = SimpleSSLWebSocketServer("localhost", 4246, DataWebSocket, "../certs/localhost.crt", "../certs/localhost.key.pem")
        else:
            server = SimpleWebSocketServer("localhost", 4246, DataWebSocket)
        print("start server: 127.0.0.1:4246")
        server.serveforever()
    
    if __name__ == "__main__":
        start_data_receiver()
    

    这是错误打印:

    ['Traceback (most recent call last):\n', '  File "data_receiver_ws2.py", line 26, in __new__\n    super().__new__(cls, cls_name, cls_bases, cls_dict)\n', 'TypeError: object() takes no parameters\n']
    Traceback (most recent call last):
      File "data_receiver_ws2.py", line 82, in <module>
        start_data_receiver()
      File "data_receiver_ws2.py", line 79, in start_data_receiver
        server.serveforever()
      File "/home/username/.local/lib/python3.6/site-packages/SimpleWebSocketServer/SimpleWebSocketServer.py", line 704, in serveforever
        super(SimpleSSLWebSocketServer, self).serveforever()
      File "/home/username/.local/lib/python3.6/site-packages/SimpleWebSocketServer/SimpleWebSocketServer.py", line 678, in serveforever
        self.serveonce()
      File "/home/username/.local/lib/python3.6/site-packages/SimpleWebSocketServer/SimpleWebSocketServer.py", line 614, in serveonce
        if client.sendq:
    AttributeError: type object 'DataWebSocket' has no attribute 'sendq'
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   Duncan    6 年前

    __new__ 需要创建的实例 cls 然后把它还给我。你回来了 CLS 本身。所以像这样:

    def __new__(cls, cls_name, cls_bases, cls_dict):
        instance = super().__new__(cls, cls_name, cls_bases, cls_dict)
        instance.udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # add udp socket as a class attribute (not instance attribute)
        instance.udp_sock.setblocking(False)
        instance.udp_sock.bind(("127.0.0.1", 6666))
        return instance
    

    你得到一个 AttributeError 你当时是想用 DataWebSocket 类型本身(从构造函数返回的)而不是它的实例,因此 __init__ 不存在。

    你没有什么问题 __init__() 方法(除非您应该抑制异常:只让异常冒泡到最高层)。 爱因斯坦 初始化传递给它的对象,它不返回任何内容。就叫超类吧 爱因斯坦 你的方式。

    新西兰 构造一个新对象,因此它必须返回它。如果返回的对象是 CLS 然后python会调用 爱因斯坦 自动地。如果您返回不同的内容(正如您在这里所做的),那么python将不会调用 爱因斯坦 为你 爱因斯坦 对于类,只能用该类(或子类)的实例调用。

        2
  •  0
  •   Benoît P    6 年前

    这是添加类属性的方法

    class DataWebSocket(WebSocket):
        my_attr = "banana"
    

    类的每个方法在技术上都与属性相同。