Как эффективно обеспечить интерфейс Web, CLI & API в Python? - PullRequest
0 голосов
/ 06 мая 2019

Моя проблема заключается в следующем. В моей библиотеке есть какая-то функция:

def some_func(arg1=1):
    pass

, который я хочу использовать тремя способами:

Использование операторов импорта в других скриптах Python:

import my_library
my_library.some_func()

Экспонирование с использованием интерфейса CLI с щелчком мыши.

@click.group()
@click.option('--arg1', default=1)
def some_func(arg1):
    pass

Экспонирование с использованием веб-интерфейса с Flask.

@app.route('/endpoint', defaults={'arg1': 1})
def some_func(arg1):
    pass

Но как я могу структурировать это эффективно, не дублируя слишком много кода?

Возможно ли объединить все три? Я попробовал (варианты) следующее, что не получается:

@click.group()
@click.option('--arg1', default=1)
@app.route('/endpoint', defaults={'arg1': 1})
def some_func(arg1=1):
    pass

Или мне действительно нужны 3 разные функции, как определено выше?

И если так, как мне перейти к значениям по умолчанию?

Является ли доступ к глобальной переменной во всех местах лучшим способом сделать это?

1 Ответ

1 голос
/ 06 мая 2019

Поскольку синтаксис декоратора является просто ярлыком для приложения функции, вы начинаете с определения своей функции в своей библиотеке.Тогда ваш click пример становится:

import my_library

click.group()(click.option('--arg1', default=1)(my_library.some_func))

, а ваш пример Flask становится

import library

app.route('/endpoint', defaults={'arg1': 1})(my_library.some_func)

(я знаю, что для Flask возвращаемое значение декоратора не важно; я полагаю,то же самое верно для click.)

Это предполагает, что вы не пытаетесь использовать один и тот же сценарий как инструмент командной строки и приложение Flask;ИМО не имеет особого смысла.


Что касается упрощения значения по умолчанию, ничего хорошего не приходит в голову.Нажмите, Flask, и у вашей функции есть три разных способа указания значения по умолчанию;единственная общая черта - это фактическое значение этого значения по умолчанию.Вы можете сделать что-то вроде этого.Сначала в my_library.py:

some_func_default = 1

def some_func(arg=None):  # Or some other sentinel
    if arg is None:
        arg = some_func_default

Затем в двух других ваших скриптах:

click.group()(click.option('--arg1', default=my_library.some_func_default)(my_library.some_func))

и

app.route('/endpoint', defaults={'arg1': my_library.some_func_default})(my_library.some_func)

Конечно, вы можете использовать inspect модуль для извлечения значения по умолчанию из вашего исходного определения some_func, но это не помогает с разницей в том, как Click и Flask устанавливают значения по умолчанию для своих точек входа.

...