Занятие REST API звонков в Python довольно распространена и просто, особенно из-за наличия библиотек, таких как Запросы .
Возьмите следующий пример:
def get_user(user_id): res = requests.get(f'https://jsonplaceholder.typicode.com/users/{user_id}') if res.ok: return res.json() else: print(f'{res.status_code}: {res.text}') return {}
Код довольно прост. Мы определяем функцию для получения деталей пользователя от API (Очень удобное веб-приложение для тестирования веб-приложений).
Простой. Верно?
Однако, что происходит, когда нет подключения? Исключения подняты. Это может легко завершить в попробуй ... кроме
пункт Но это делает наш код грязным, особенно когда у нас есть несколько конечных точек, чтобы позвонить.
Введите Возвращает Отказ
Возврат – библиотека, написанная с учетом безопасности. Это довольно мощно и имеет много, чтобы предложить. Теперь давайте быстро исправить наши небезопасный код.
class GetUser(object): @pipeline def __call__(self, user_id: int) -> Result[dict, Exception]: res = self._make_request(user_id).unwrap() return self._parse_json(res) @safe def _make_request(self, user_id: int) -> requests.Response: res = requests.get(f'https://jsonplaceholder.typicode.com/users/{user_id}') res.raise_for_status() return res @safe def _parse_json(self, res: requests.Response) -> dict: user = res.json() return user get_user = GetUser()
Мы определили класс, который можно вызвать как функцию, когда-то создается. Нам нужно принять к сведению @safe
Декоратор, очень удобный декоратор, который обернет любое исключение, поднятое в Провал
объект. Провал
Класс – это подкласс Результат
Тип, который в основном является простым контейнером. Теперь наш код изменяется с:
try: user = get_user(1) except Exception: print('An error occurred')
к:
user = get_user(1) # returns Success(dict) or Failure(Exception) user = user.value_or({})
Разве это не просто элегантно?
Я знаю, что вы думаете. Это слишком много кода! Это то же самое, что я подумал сначала. Но после игры с библиотекой и немного настройки я начал замечать, что мой код выглядел чище. Я мог бы быстро отсканировать через файл и получить суть того, что идет без необходимости следовать ссылками. Это просто поверхность. Возврат имеет способ больше предложить. Проверьте это OUT Отказ
Вот декоратор, который я придумал, чтобы автоматически развернуть Результат
Внутренние значения или дайте значение по умолчанию:
def unwrap(success=None, failure=None): def outer_wrapper(func): @functools.wraps(func) def wrapper(*args, **kwargs): result = func(*args, **kwargs) if is_successful(result): if success is not None: return success else: if failure is not None: return failure return result._inner_value return wrapper return outer_wrapper
Использование:
@unwrap(failure={}) # If a failure occurs an empty dict is returnd @pipeline def __call__(self, user_id: int) -> Result[dict, Exception]: ... user = get_user(1) # returns dict or empty dict
Ваше здоровье!
Оригинал: “https://dev.to/michaelbukachi/making-safe-api-calls-with-python-2nbk”