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