Простая система плагинов Python - PullRequest
0 голосов
/ 17 июня 2009

Я пишу парсер для внутреннего формата метаданных на основе xml в python. Мне нужно предоставить разные классы для обработки разных тегов. Потребуется довольно большая коллекция обработчиков, поэтому я представлял ее как простую систему плагинов. Я хочу просто загрузить каждый класс в пакете и зарегистрировать его в моем парсере. Моя текущая попытка выглядит так:
(Обработчики - это пакет, содержащий обработчики, каждый обработчик имеет теги статического члена, который является кортежем строк)

class MetadataParser:
    def __init__(self):
        #...
        self.handlers={}
        self.currentHandler=None
        for handler in dir(Handlers): # Make a list of all symbols exported by Handlers
            if handler[-7:] == 'Handler': # and for each of those ending in "Handler"
                handlerMod=my_import('MetadataLoader.Handlers.' + handler)
                self.registerHandler(handlerMod, handlerMod.tags) # register them for their tags

    # ...

    def registerHandler(self, handler, tags):
        """ Register a handler class for each xml tag in a given list of tags """
        if not isSequenceType(tags): 
            tags=(tags,) # Sanity check, make sure the tag-list is indeed a list
        for tag in tags:
            self.handlers[tag]=handler

Однако это не работает. Я получаю ошибку AttributeError: 'module' object has no attribute 'tags' Что я делаю неправильно?

Ответы [ 4 ]

0 голосов
/ 28 августа 2015

Простая и полностью расширяемая реализация с помощью библиотеки exte_me .

Код может выглядеть как

from extend_me import ExtensibleByHash

# create meta class
tagMeta = ExtensibleByHash._('Tag', hashattr='name')

# create base class for all tags
class BaseTag(object):
    __metaclass__ = tagMeta

    def __init__(self, tag):
        self.tag = tag

    def process(self, *args, **kwargs):
        raise NotImeplemntedError()

# create classes for all required tags
class BodyTag(BaseTag):
    class Meta:
        name = 'body'

    def process(self, *args, **kwargs):
        pass  # do processing

class HeadTag(BaseTag):
    class Meta:
        name = 'head'

    def process(self, *args, **kwargs):
        pass  # do some processing here

# implement other tags in this way
# ...

# process tags
def process_tags(tags):
    res_tags = []
    for tag in tags:
        cls = tagMeta.get_class(tag)  # get correct class for each tag
        res_tags.append(cls(tag))  # and add its instance to result
    return res_tags

Для получения дополнительной информации см. документацию или код . Эта библиотека используется в OpenERP / Odoo RPC lib

0 голосов
/ 17 июня 2009

Я предлагаю вам прочитать пример и объяснение на этой странице , где объясняется, как написать архитектуру плагина.

0 голосов
/ 06 июля 2009

Во-первых, извинения за плохо сформированный / неправильный код.
Также спасибо за просмотр. Однако виновник был, как это часто бывает, между креслом и клавиатурой. Я запутался, имея классы и модули с тем же именем. Результат my_import (который я теперь понимаю, я даже не упомянул, откуда он взялся ... Это из SO: link ) - это модуль, названный, например, areaHandler. Я хочу класс, также называемый areaHandler. Поэтому мне просто нужно было выбрать класс по eval ('Handlers.' + Handler + '.' + Handler).
Еще раз спасибо за ваше время и извините за пропускную способность

0 голосов
/ 17 июня 2009

Возможно, один из ваших handlerMod модулей не содержит никакой переменной tags.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...