Автообнаружение Python декораторов - PullRequest
0 голосов
/ 22 ноября 2018

Мне было интересно, существует ли стандартизированный подход или наилучшая практика для сканирования / автообнаружения декораторов, как это делается здесь , но также и в некоторых других библиотеках, таких как Django, Flask.Обычно декоратор предоставляет дополнительную / упакованную функциональность прямо в то время, когда вызывается внутренняя функция.

В примере, показанном ниже, но также и во Flask / Django (декораторы маршрутов), декоратор скорее используется для добавления всеобъемлющих функций, например, порождает tcp-клиент изначально в логике декоратора, а затем вызывает внутренний функционал, когда естьэто сообщение, полученное для его обработки.

Регистр Flask / Django для URL-маршрута, где внутренний функционал вызывается только позже, когда запрашивается URL-адрес.Все примеры требуют начальной регистрации (сканирования / обнаружения) логики декоратора, чтобы также изначально запустить всеобъемлющую функциональность.Мне кажется, что это альтернативное использование декораторов, и я хотел бы понять подход наилучшей практики, если таковой имеется.

См. Ниже пример 1011 * Faust , где decorator app.agent () автоматическизапускает клиент прослушивания (поток kafka) в цикле событий asyncio, и входящее сообщение затем обрабатывается внутренней функцией hello () позже, только когда получено сообщение , требующее начальной проверки / сканирования / обнаружениясначала связанная логика декоратора в начале скрипта.

import faust

class Greeting(faust.Record):
    from_name: str
    to_name: str

app = faust.App('hello-app', broker='kafka://localhost')
topic = app.topic('hello-topic', value_type=Greeting)

@app.agent(topic)
async def hello(greetings):
    async for greeting in greetings:
        print(f'Hello from {greeting.from_name} to {greeting.to_name}')

@app.timer(interval=1.0)
async def example_sender(app):
    await hello.send(
        value=Greeting(from_name='Faust', to_name='you'),
    )

if __name__ == '__main__':
    app.main()

1 Ответ

0 голосов
/ 23 ноября 2018

Ничего не "обнаружено".Когда вы import модуль из пакета, весь этот код выполняется.Вот почему у нас есть if __name__ == '__main__', чтобы остановить выполнение определенного кода при импорте.Декораторы будут «обнаружены», когда вы запустите ваш код.

Я думаю, Flask blueprint - хороший пример. Здесь вы можете увидеть, как он регистрирует конечные точки URL при импорте модулей.Все, что он делает, это добавляет к списку:

    def route(self, rule, **options):
        """Like :meth:`Flask.route` but for a blueprint.  The endpoint for the
        :func:`url_for` function is prefixed with the name of the blueprint.
        """
        def decorator(f):
            endpoint = options.pop("endpoint", f.__name__)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator

Код выполняется, декораторы оцениваются, и им нужно только сохранить некоторый внутренний список всех функций, которые они декорируют.Они хранятся в объекте Blueprint.

...