Twisted Python 接口实例是否可以不实现该接口的所有功能?

Can Twisted Python interface instance not implementing all functions of that interface?

正如我在这个 blog, I found that when ClientFactory instance, which is an argument to PoetryClientFactory, or Protocol instance, which is an argument to PoetryProtocol, is not implementing all the functions defined for ClientFactory or Protocol interface. ClientFactory 接口实现 startedConnecting、clientConnectionFailed 和 clientConnectionLost 中的示例一样,但 PoetryClientFactory 不实现 startedConnecting 和 clientConnectionLost。怎么了?

# This is the Twisted Get Poetry Now! client, version 2.0.

# NOTE: This should not be used as the basis for production code.

import datetime, optparse

from twisted.internet.protocol import Protocol, ClientFactory


def parse_args():
    usage = """usage: %prog [options] [hostname]:port ...

This is the Get Poetry Now! client, Twisted version 2.0.
Run it like this:

  python get-poetry.py port1 port2 port3 ...

If you are in the base directory of the twisted-intro package,
you could run it like this:

  python twisted-client-2/get-poetry.py 10001 10002 10003

to grab poetry from servers on ports 10001, 10002, and 10003.

Of course, there need to be servers listening on those ports
for that to work.
"""

    parser = optparse.OptionParser(usage)

    _, addresses = parser.parse_args()

    if not addresses:
        print parser.format_help()
        parser.exit()

    def parse_address(addr):
        if ':' not in addr:
            host = '127.0.0.1'
            port = addr
        else:
            host, port = addr.split(':', 1)

        if not port.isdigit():
            parser.error('Ports must be integers.')

        return host, int(port)

    return map(parse_address, addresses)


class PoetryProtocol(Protocol):

    poem = ''
    task_num = 0

    def dataReceived(self, data):
        self.poem += data
        msg = 'Task %d: got %d bytes of poetry from %s'
        print  msg % (self.task_num, len(data), self.transport.getPeer())

    def connectionLost(self, reason):
        self.poemReceived(self.poem)

    def poemReceived(self, poem):
        self.factory.poem_finished(self.task_num, poem)


class PoetryClientFactory(ClientFactory):

    task_num = 1

    protocol = PoetryProtocol # tell base class what proto to build

    def __init__(self, poetry_count):
        self.poetry_count = poetry_count
        self.poems = {} # task num -> poem

    def buildProtocol(self, address):
        proto = ClientFactory.buildProtocol(self, address)
        proto.task_num = self.task_num
        self.task_num += 1
        return proto

    def poem_finished(self, task_num=None, poem=None):
        if task_num is not None:
            self.poems[task_num] = poem

        self.poetry_count -= 1

        if self.poetry_count == 0:
            self.report()
            from twisted.internet import reactor
            reactor.stop()

    def report(self):
        for i in self.poems:
            print 'Task %d: %d bytes of poetry' % (i, len(self.poems[i]))

    def clientConnectionFailed(self, connector, reason):
        print 'Failed to connect to:', connector.getDestination()
        self.poem_finished()


def poetry_main():
    addresses = parse_args()

    start = datetime.datetime.now()

    factory = PoetryClientFactory(len(addresses))

    from twisted.internet import reactor

    for address in addresses:
        host, port = address
        reactor.connectTCP(host, port, factory)

    reactor.run()

    elapsed = datetime.datetime.now() - start

    print 'Got %d poems in %s' % (len(addresses), elapsed)


if __name__ == '__main__':
    poetry_main()

我不认为我很确定你在问什么,但基本上如果你不需要对某个事件采取行动(例如当客户端开始连接或连接丢失时),您不需要实现该功能。它主要只是一个界面。如果您不实现这些函数,则会调用一个什么都不做的空函数,来自 ClientFactoryProtocol,或者您从中继承的任何一个 class..

我也不太清楚你在问什么。

IMO,他们的 source code 达到 github 是最快的学习方法。如您所见,startedConnectingclientConnectionLost 有默认实现(尽管是空代码)。

因此,您只需要实现您需要的回调,而不是该接口中定义的所有方法。

如果你自己实现一个接口,它看起来像这样:

from zope.interface import implementer
from twisted.internet.interfaces import IProtocol
@implementer(IProtocol)
class MyProtocol(object):
    " ... "

在这种情况下,您确实需要实现所有方法,因为这个@implementer声明只是说您打算提供所有相关方法。

然而,在Twisted中更常见的做法是subclass,像这样:

from twisted.internet.protocol import Protocol
class MyProtocol(Protocol, object):
    " ... "

this情况下,你不需要实现所有的方法,因为Protocolsuper-class 已经提供了 IProtocol 上所有方法的实现。通常,Twisted 提供了一个超级class,它具有所有方法的默认版本或空版本,用于 Twisted 应用程序开发人员必须实现的许多更常用的接口。