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

时间:2015-07-29 22:21:35

标签: python twisted

当我通过这个blog中的例子时,我发现当ClientFactory实例(PoetryClientFactory的一个参数)或者是PoetryProtocol的一个参数的Protocol实例时,它没有实现定义的所有函数用于ClientFactory或Protocol接口。 ClientFactory接口实现了startsConnecting,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()

3 个答案:

答案 0 :(得分:2)

我认为我不确定你在问什么,但基本上如果你不需要对某个事件采取行动(例如当客户开始连接或连接丢失时),你就不要不需要实现这个功能。它主要是一个界面。如果你没有实现这些函数,那么从ClientFactoryProtocol或者你继承的任何一个类调用一个不执行任何操作的空函数。

答案 1 :(得分:2)

如果您自己实现界面,它看起来像这样:

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

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

然而,在Twisted中更常见的事情是子类化,如下所示:

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

这个的情况下,你需要实现所有方法,因为Protocol超类已经提供了{{{{}}上所有方法的实现1}}。通常,Twisted提供了一个超类,它具有Twisted应用程序开发人员必须实现的许多更常用接口的所有方法的默认或空版本。

答案 2 :(得分:0)

我也不太确定你在问什么。

IMO,达到github的source code是最快的学习方式。如您所见, startedConnecting clientConnectionLost (默认为空代码)有默认实现。

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