Как я могу добавить атрибут класса в Python? - PullRequest
0 голосов
/ 28 января 2019

Я хочу создать класс, который передает данные из 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 ]

0 голосов
/ 28 января 2019

__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__ для класса можно вызывать только с экземпляром этого класса (или подкласса).

0 голосов
/ 28 января 2019

Вот как вы добавляете атрибуты класса

class DataWebSocket(WebSocket):
    my_attr = "banana"

Каждый метод вашего класса технически совпадает с атрибутом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...