更改socket对象的__class__属性时的TypeError

时间:2017-07-10 14:06:22

标签: python sockets

有以下服务器代码(我定义了一个继承自socket的类,并尝试使用该类调用客户端套接字上的send方法):

import socket

class LogSocket(socket.socket):
    def send(self, data):
        print("Sending {0} to {1}".format(
            data, self.getpeername()[0]))
        super().send(data)

def respond(client):
    response = input("Enter a value: ")
    client.send(bytes(response, 'utf8'))
    client.close()

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('',2401))
server.listen(1)
try:
    while True:
        client, addr = server.accept()
        client.__class__ = LogSocket
        respond(client)
finally:
    server.close()

客户端代码是:

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('localhost', 2401))
print("Received: {0}".format(client.recv(1024)))
client.close()

当我运行上面的代码时,服务器崩溃并出现错误:

Traceback (most recent call last):
  File "10_04_server.py", line 20, in <module>
    client.__class__ = LogSocket
TypeError: __class__ assignment: 'LogSocket' object layout differs from 'socket'

这个错误是什么意思?它为什么会发生?

1 个答案:

答案 0 :(得分:2)

__slots__属性设置为(),这样就可以了:

class LogSocket(socket.socket):
    __slots__ = ()
    def send(self, data):
        print("Sending {0} to {1}".format(
            data, self.getpeername()[0]))
        super().send(data)

relevant pieces of documentation是:

  

__slots__声明的操作仅限于定义它的类。因此,子类将具有__dict__,除非它们还定义__slots__(其中必须只包含任何其他插槽的名称)。

  仅当两个类具有相同的__class__时,

__slots__赋值才有效。