使用新属性扩展 socket.socket

Extending socket.socket with a new attribute

我希望用新属性扩展 Python socket.socket(特别是 queue.Queue,但可以是任何其他属性)。我在尝试 决定我应该使用继承还是组合,但在某些时候两者都构成 问题我不确定如何解决:

A) 如果我使用继承,比如:

class MySocket(socket.socket):
    def __init__(self, *args, **kwargs):
        socket.socket.__init__(self, *args, **kwargs)
        self.queue = queue.Queue()

然后我在使用像

这样的操作时遇到问题
connection, client_address = s.accept()

因为套接字 returns 类型 socket.socket 对象的 accept 方法,而不是 MySocket 类型的对象, 而且我不确定如何将一个转换为另一个。如果有一个简单的 OOP 方法可以做到这一点, 我不知道。

B) 如果我改用组合,前面的问题就很容易解决了:

class MySocket(socket.socket):
    def __init__(self, true_socket):
        self.true_socket = true_socket
        self.queue = queue.Queue()

我会简单地实现类似

的东西
def accept(self, *args, **kwargs):
    con, cli = socket.socket.accept(self, *args, **kwargs)
    return self.__class__(con), cli

但是我还有另一个问题。当我需要做的时候

readable, writable, exceptional = select.select(inputs, outputs, inputs)

select 适用于 socket.socket。对于 A) 版本,我希望它能按原样工作, 但是有了组合,现在 MySockets 不是 socket.socket 的实例,select 被破坏了。

那么,对此最好的 pythonistic 方法是什么?

编辑:我忘了说我尝试的第一件事是将属性直接添加到“socket.socket”的实例中:

s = socket.socket(...)
s.queue = queue.Queue()

但是我得到一个异常,说 'socket.socket' 的属性未知。

也许你应该尝试继承 super

class NewSocket(socket.socket):
    def __init__(self):
        super(NewSocket, self).__init__()

您可以使用以下内容,基于 socket.socket.dup() in Lib/socket.py

    import _socket

    class MySocket(socket.socket):
        def __init__(self, *args, **kwargs):
            super(MySocket, self).__init__(*args, **kwargs)
            self.queue = queue.Queue

        @classmethod
        def copy(cls, sock):
            fd = _socket.dup(sock.fileno())
            copy = cls(sock.family, sock.type, sock.proto, fileno=fd)
            copy.settimeout(sock.gettimeout())
            return copy

您现在可以使用构造函数创建新的 MySocket,或使用 MySocket.copy() 从现有的 socket.socket 创建 MySocket。请注意,在大多数情况下,您应该在创建副本后关闭原始套接字。