如何在Python中添加类属性?

时间:2019-01-28 14:34:39

标签: python python-3.x class websocket

我想创建一个类,将数据从websocket传输到udp套接字。
此代码使用simple-websocket-server模块来实现websocket服务器。
因此,我试图将udp套接字添加为类属性,但会引发错误。 我该如何解决?

请注意,我知道当DataWebSocket对象传递给SimpleSSLWebSocketServer时,此错误能够避免使用闭包。
但是我想尝试对udp套接字进行嵌入式,并且我想了解python中的class属性。

这是代码:

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 个答案:

答案 0 :(得分:2)

__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__()方法没有什么大不了(除非您应该抑制异常:只需让异常冒泡到顶层即可)。 __init__初始化传递给它的对象,它不返回任何内容。只需按您的方式调用超类__init__

__new__构造一个新对象,因此它必须返回它。如果返回的对象是cls的实例,则Python将自动调用__init__。如果您返回不同的内容(如此处所做的操作),那么Python不会为您调用__init__,因为类的__init__只能用该类(或子类)的实例来调用。 / p>

答案 1 :(得分:0)

这是添加类属性的方式

class DataWebSocket(WebSocket):
    my_attr = "banana"

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