Правильный способ создать IRC-бота на Python?

#python #regex #parsing #sockets #irc

#python #регулярное выражение #синтаксический анализ #сокеты #irc

Вопрос:

Итак, я начинаю писать простого процедурного IRC-бота на Python с нуля (т. Е. необработанные сокеты) и пытаюсь выработать наилучший способ его проектирования.

Обычно у меня есть большой старый цикл while (), который будет сидеть там и помещать данные, полученные из сокета, в буфер, и я буду использовать массивный оператор if / else для сканирования строки (используя регулярные выражения), чтобы решить, что с этим делать. У меня такое чувство, что я не должен этого делать, потому что это ужасно.

Я решил составить словарь регулярных выражений и связанных с ними значений, например

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

и просто используйте цикл for / in для поиска по тексту и выяснения, какое регулярное выражение ему соответствует. Я зашел так далеко, и первое, о чем я подумал, было «хорошо, я могу просто сделать так, чтобы каждая «процедура» вызывалась, когда определенное регулярное выражение соответствует функции, и вызывать соответствующую функцию на основе значения. Я либо застрял с использованием массивного оператора if / else, чего я не хотел делать в первую очередь, либо я мог бы использовать какой-нибудь Pythonic ‘eval’, который немедленно вызывает тревогу.

В любом случае я облажался, и я не могу придумать, как подойти к этому, не переходя полностью на ООП (я не планирую делать это в данный момент, не спрашивайте почему).

Есть идеи?

Комментарии:

1. вот как я сделал github.com/mouuff/MouBot

2. Я знаю, вы сказали «с нуля», но вы можете захотеть взглянуть на Supybot, если вы еще этого не сделали. Он написан на Python и предназначен для расширения.

Ответ №1:

 def incoming_ping():
    pass

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

Вместо строк используйте ссылки на функции.

ps. Если вы «серьезно» относитесь к IRC-боту, возможно, вам захочется взглянуть на Twisted.

Комментарии:

1. Это именно то, что я ищу! Я думал в этом направлении, но я не знал, что вы действительно можете ссылаться на функции в словарях. Спасибо!

2. Вы можете ссылаться на них где угодно — в Python функции являются объектами первого класса.

3. Решение @Kye samplebias лучше и выполняется так, как это обычно делается. Выполнение этого способа дает вам больше свободы в том, что вы хотите принять в качестве команды.

Ответ №2:

Напишите универсальный анализатор протокола IRC, который может быть основан на регулярных выражениях. Кажется немного излишним писать отдельное регулярное выражение для каждой отдельной команды ( ^PINGs, ^PRIVMSGs ), когда команды следуют более общему шаблону ( ^[A-Z]s ).

Затем, после того как вы проанализировали команду, вы можете найти метод / функцию, которые выполняют эту команду, с помощью getattr(obj, 'irc_%s' % command) .

Преимущество в том, что вам не нужно поддерживать все ваши методы плюс таблицу сопоставления с шаблоном для каждой команды.

Этот метод используется в IRC-клиенте Twisted:

 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
    ...