Python IRC 机器人该如何正确实现?
我正在从零开始写一个简单的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这个库。