'METHODNAME'作为客户端方法与irc_'METHODNAME'在扭曲中

时间:2010-06-30 21:46:56

标签: python client twisted libraries irc

看看twisted.words.protocols.irc.IRCClient,在我看来,有一些奇怪的冗余方法。例如,有一个方法'privmsg',但也有一个方法'irc_PRIVMSG'

另一个例子是'join'和'irc_JOIN'

我想知道的是为什么冗余,这只是众多的两个例子。这两种不同的类型是否在不同的环境中使用?我们应该使用一种类型而不是另一种吗?

1 个答案:

答案 0 :(得分:4)

关于在不同环境中使用的两种不同类型的方法,您正走在正确的轨道上。通过检查IRCClient处理它接收的数据的方式,实际上可以很容易地看到这一点。首先它将它们分解成行,然后将行分开并将这些段传递给它自己的handleCommand方法:

def handleCommand(self, command, prefix, params):
    """Determine the function to call for the given command and call
    it with the given arguments.
    """
    method = getattr(self, "irc_%s" % command, None)
    try:
        if method is not None:
            method(prefix, params)
        else:
            self.irc_unknown(prefix, command, params)
    except:
        log.deferr()

这是一个在Twisted协议实现中非常常见的模式示例,更常见的是,在整个Python程序中。某些输入用于动态构造方法名称。然后getattr用于查找该方法。如果找到了,就会被调用。

由于服务器正在发送“PRIVMSG ...”和“JOIN ...”等客户端行,因此IRCClient会查找irc_PRIVMSGirc_JOIN等方法。

这些irc_*方法只是通过拆分调用,但是未解析的剩余部分。这提供了消息附带的所有信息,但它并不总是最好的数据格式。例如,JOIN消息包含包含主机掩码的用户名,但主机掩码通常不相关且仅昵称是理想的。因此JOINirc_*方法做了一些相当典型的事情:它将粗略数据转换为更令人愉快的工作并将结果传递给userJoined

def irc_JOIN(self, prefix, params):
    """  
    Called when a user joins a channel.
    """
    nick = string.split(prefix,'!')[0]
    channel = params[-1]
    if nick == self.nickname:
        self.joined(channel)
    else:
        self.userJoined(nick, channel)

您可以看到此处还有一个条件,有时会调用joined而不是userJoined。这是从低级数据转换为应该更方便应用程序开发人员使用的东西的另一个例子。

此分层应该可以帮助您确定在处理事件时要覆盖哪些方法。如果最高级别的回调(例如userJoinedjoinedprivmsg)足以满足您的要求,那么您应该使用这些回调,因为它们会使您的任务变得最简单。另一方面,如果他们以不方便的格式呈现数据或者以其他方式难以使用,您可以下拉到irc_*级别。将调用您的方法而不是IRCClient上定义的方法,因此您可以处理较低级别格式的数据,甚至不会调用更高级别的回调(除非您还调用基本实现)覆盖方法)。

您还会发现有IRCClient甚至没有定义irc_*方法的IRC消息。正如我们在handleCommand方法中看到的那样,这些都转到irc_unknown回调。但是,如果在irc_*子类上定义IRCClient方法,则handleCommand将开始将数据传递给该方法。显然,在这些情况下,您唯一的选择是定义irc_*方法,因为没有更高级别的回调(例如privmsg / irc_PRIVMSG案例中的privmsg)。

您可以构建irc_*方法的实现,类似于IRCClient的方式,如果您愿意 - 我通常会发现这样做很有帮助,因为它使单元测试更容易并保持协议解析逻辑与应用程序逻辑分开 - 但这取决于你。