Python IRC 机器人该如何正确实现?

0 投票
2 回答
1207 浏览
提问于 2025-04-16 16:36

我正在从零开始写一个简单的Python IRC机器人(也就是用原始套接字),现在在考虑怎么设计它比较好。

通常我会有一个很大的while循环,它会一直运行,把从套接字接收到的数据放进一个缓冲区,然后用一个庞大的if/else语句来检查这些数据(用正则表达式),看看该怎么处理这些数据。我感觉这样做不太对,因为这让人感觉很糟糕。

我决定做一个正则表达式和它们对应含义的字典,比如:

regexes = {"^PING: (.+)": "incomming_ping",
           "more regex": "more meanings"}

然后我可以用一个for/in循环来遍历文本,找出哪个正则表达式匹配。到目前为止,我想到了一个主意:“好吧,我可以把每个‘过程’(也就是当某个正则表达式匹配时要执行的操作)做成一个函数,然后根据它的含义调用相应的函数。”但是我要么还是得用一个庞大的if/else语句,这正是我不想做的,或者我可以用某种Python的‘eval’功能,这让我觉得很不安。

不管怎样,我都觉得很糟糕,我想不出其他方法来解决这个问题,而不完全使用面向对象编程(我现在不打算这样做,别问为什么)。

有没有什么好主意?

2 个回答

2

写一个通用的IRC协议解析器,可以基于正则表达式来实现。为每个不同的命令(比如^PING\s^PRIVMSG\s)写一个单独的正则表达式似乎有点多余,因为这些命令其实遵循一个更一般的模式(^[A-Z]\s)。

一旦你解析出一个命令,就可以通过getattr(obj, 'irc_%s' % command)来查找执行该命令的方法或函数。

这样做的好处是,你不需要维护所有的方法,还要额外维护一个每个命令对应模式的映射表。

这个技巧在Twisted的IRC客户端中使用:

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)

def irc_JOIN(self, prefix, params):
    # perform the JOIN action
    ...

def irc_unknown(self, prefix, command, params):
    # unknown command
    ...
2
def incoming_ping():
    pass

regexes = {"^PING: (.+)": incoming_ping,
           "more regex": "more meanings"}

与其使用字符串,不如直接用函数的引用。

顺便说一下,如果你对IRC机器人这件事“很认真”,可以看看Twisted这个库。

撰写回答