繁体   English   中英

如何在Python中添加类属性?

[英]How I can add class attribute in Python?

我想制作一个类,将数据从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'

__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__只能使用该类(或子类)的实例来调用。

这是添加类属性的方式

class DataWebSocket(WebSocket):
    my_attr = "banana"

从技术上讲,您的类的每个方法都与属性相同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM