Пакет Python для анализа и проверки данных

Сегодняшняя тема посвящена проверке данных и управлению настройками с использованием подсказок типов Python. Мы собираемся использовать пакет Python под названием pydantic, который применяет подсказки типа во время выполнения. Он предоставляет удобные для пользователя ошибки, позволяющие выявлять любые недопустимые данные. Основываясь на официальной документации, Pydantic

«… В первую очередь библиотека синтаксического анализа, а не библиотека проверки. Валидация - это средство для достижения цели: построение модели, которая соответствует предоставленным типам и ограничениям.

Другими словами, pydantic гарантирует типы и ограничения выходной модели, а не входные данные ».

В этом руководстве есть три раздела:

  1. Настраивать
  2. Реализация
  3. Заключение

Переходим к следующему разделу и приступаем к установке необходимых модулей.

1. Настройка

Перед продолжением установки настоятельно рекомендуется создать виртуальную среду.

Базовая установка

Откройте терминал и выполните следующую команду, чтобы установить pydantic

pip install pydantic

Обновить существующий пакет

Если у вас уже есть существующий пакет и вы хотите его обновить, пожалуйста, выполните следующую команду:

pip install -U pydantic

Анаконда

Для пользователей Anaconda вы можете установить его следующим образом:

conda install pydantic -c conda-forge

Необязательные зависимости

pydantic поставляется со следующими необязательными зависимостями в зависимости от ваших потребностей:

  • email-validator - Поддержка проверки электронной почты.
  • typing-extensions - Поддержка использования Literal до Python 3.8.
  • python-dotenv - Поддержка dotenv файла с настройками.

Вы можете установить их вручную:

# install email-validator
pip install email-validator
# install typing-extensions
pip install typing_extensions
# install python-dotenv
pip install python-dotenv

или вместе с pydantic следующим образом:

# install email-validator
pip install pydantic[email]
# install typing-extensions
pip install pydantic[typing_extensions]
# install python-dotenv
pip install pydantic[dotenv]
# install all dependencies
pip install pydantic[email,typing_extensions,dotenv]

2. Реализация

В этом разделе мы собираемся изучить некоторые полезные функции, доступные в pydantic.

Определить объект в pydantic так же просто, как создать новый класс, унаследованный отBaseModel. Когда вы создаете новый объект из класса, pydantic гарантирует, что поля результирующего экземпляра модели будут соответствовать типам полей, определенным в модели.

Импортировать

Добавьте следующее объявление импорта в верхнюю часть файла Python.

from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel

Класс пользователя

Объявите новый класс, наследующий BaseModel, как показано ниже:

class User(BaseModel):
    id: int
    username : str
    password : str
    confirm_password : str
    alias = 'anonymous'
    timestamp: Optional[datetime] = None
    friends: List[int] = []

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

  • id - Целочисленная переменная представляет идентификатор. Поскольку значение по умолчанию не предоставляется, это поле является обязательным и должно быть указано при создании объекта. Если возможно, строки, байты или числа с плавающей точкой будут преобразованы в целые числа; в противном случае возникнет исключение.
  • username — Строковая переменная представляет имя пользователя и является обязательной.
  • password - Строковая переменная представляет пароль и является обязательной.
  • confirm_password - Строковая переменная представляет собой пароль подтверждения и является обязательной. Позже он будет использоваться для проверки данных.
  • alias — Строковая переменная представляет псевдоним. Он не является обязательным и будет установлен анонимным, если он не будет предоставлен во время создания объекта.
  • timestamp - Поле даты / времени, которое не является обязательным. По умолчанию - Нет. pydantic будет обрабатывать либо временную метку unix int, либо строку, представляющую дату / время.
  • friends - список целочисленных входов.

Создание экземпляра объекта

Следующим шагом является создание экземпляра нового объекта из класса User.

data = {'id': '1234', 'username': 'wai foong', 'password': 'Password123', 'confirm_password': 'Password123', 'timestamp': '2020-08-03 10:30', 'friends': [1, '2', b'3']}
user = User(**data)

При распечатке переменной user вы должны получить следующий результат. Вы можете заметить, что id был автоматически преобразован в целое число, даже если ввод является строкой. Точно так же байты автоматически преобразуются в целые числа, как показано в поле friends.

id=1234 username='wai foong' password='Password123' confirm_password='Password123' timestamp=datetime.datetime(2020, 8, 3, 10, 30) friends=[1, 2, 3] alias='anonymous'

Методы и атрибуты в BaseModel

Классы, наследующие BaseModel, будут иметь следующие методы и атрибуты:

  • dict() - возвращает словарь полей и значений модели.
  • json() - возвращает словарь строкового представления JSON
  • copy() - возвращает глубокую копию модели
  • parse_obj() - утилита для загрузки любого объекта в модель с обработкой ошибок, если объект не является словарем
  • parse_raw() - утилита для загрузки строк различных форматов
  • parse_field() - аналогичен parse_raw(), но предназначен для файлов
  • from_orm() — загружает данные в модель из произвольного класса
  • schema() — возвращает словарь, представляющий модель в виде схемы JSON.
  • schema_json() - возвращает строковое представление JSON schema()
  • construct() - метод класса для создания моделей без запуска валидации
  • __fields_set__ - Набор имен полей, которые были установлены при инициализации экземпляра модели
  • __fields__ - словарь полей модели
  • __config__ - класс конфигурации модели.

Давайте изменим ввод для id на строку следующим образом:

data = {'id': 'a random string', 'username': 'wai foong', 'password': 'Password123', 'confirm_password': 'Password123', 'timestamp': '2020-08-03 10:30', 'friends': [1, '2', b'3']}
user = User(**data)

При запуске кода вы должны получить следующую ошибку.

value is not a valid integer (type=type_error.integer)

Ошибка проверки

Чтобы получить более подробную информацию об ошибке, настоятельно рекомендуется заключить ее в блок try-catch следующим образом:

from pydantic import BaseModel, ValidationError
# ... codes for User class
data = {'id': 'a random string', 'username': 'wai foong', 'password': 'Password123', 'confirm_password': 'Password123', 'timestamp': '2020-08-03 10:30', 'friends': [1, '2', b'3']}
try:
    user = User(**data)
except ValidationError as e:
    print(e.json())

Он распечатает следующий JSON, который указывает, что ввод для id не является допустимым целым числом.

[
  {
    "loc": [
      "id"
    ],
    "msg": "value is not a valid integer",
    "type": "type_error.integer"
  }
]

Типы полей

pydantic обеспечивает поддержку большинства распространенных типов из стандартной библиотеки Python. Полный список выглядит следующим образом:

  • bool
  • int
  • плавать
  • ул.
  • байты
  • список
  • кортеж
  • диктовать
  • установленный
  • морозильник
  • datetime.date
  • datetime.time
  • datetime.datetime
  • datetime.timedelta
  • набор текста. любой
  • typing.TypeVar
  • набор текста.
  • набор текста.
  • набор текста.
  • typing.Tuple
  • набор. диктат
  • набор.
  • typing.FrozenSet
  • типизация. последовательность
  • набор текста.
  • typing.Type
  • набор текста.
  • набор текста.
  • ipaddress.IPv4Address
  • ipaddress.IPv4Interface
  • ipaddress.IPv4Network
  • ipaddress.IPv6Address
  • ipaddress.IPv6Interface
  • ipaddress.IPv6Network
  • enum.Enum
  • enum.IntEnum
  • десятичный. десятичный
  • pathlib.Path
  • uuid.UUID
  • ByteSize

Ограниченные типы

Вы можете установить собственное ограничение через Constrained Types. Давайте посмотрим на следующий пример:

from pydantic import (
    BaseModel,
    NegativeInt,
    PositiveInt,
    conint,
    conlist,
    constr
)
class Model(BaseModel):
    # minimum length of 2 and maximum length of 10
    short_str: constr(min_length=2, max_length=10)
    # regex
    regex_str: constr(regex=r'^apple (pie|tart|sandwich)$')
    # remove whitespace from string
    strip_str: constr(strip_whitespace=True)

    # value must be greater than 1000 and less than 1024
    big_int: conint(gt=1000, lt=1024)
    
    # value is multiple of 5
    mod_int: conint(multiple_of=5)
    
    # must be a positive integer
    pos_int: PositiveInt
    
    # must be a negative integer
    neg_int: NegativeInt

    # list of integers that contains 1 to 4 items
    short_list: conlist(int, min_items=1, max_items=4)

Строгие типы

Если вы ищете жесткие ограничения, которые проходят проверку тогда и только тогда, когда проверяемое значение относится к соответствующему типу или является подтипом этого типа, вы можете использовать следующие строгие типы:

  • StrictStr
  • StrictInt
  • StrictFloat
  • StrictBool

В следующем примере показан правильный способ принудительного применения StrictBool в унаследованном классе.

from pydantic import BaseModel, StrictBool,
class StrictBoolModel(BaseModel):
    strict_bool: StrictBool

Строка ‘False’ вызовет ошибку ValidationError, поскольку она будет принимать только True или False в качестве входных данных.

Валидатор

Кроме того, вы можете создавать свои собственные валидаторы, используя декоратор validator внутри унаследованного класса. Давайте посмотрим на следующий пример, который определяет, состоит ли id из четырех цифр и совпадает ли confirm_password с полем password.

from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel, ValidationError, validator
class User(BaseModel):
    id: int
    username : str
    password : str
    confirm_password : str
    alias = 'anonymous'
    timestamp: Optional[datetime] = None
    friends: List[int] = []
    @validator('id')
    def id_must_bepydanticdigits(cls, v):
        if len(str(v)) != 4:
            raise ValueError('must be 4 digits')
        return v
    @validator('confirm_password')
    def passwords_match(cls, v, values, **kwargs):
        if 'password' in values and v != values['password']:
            raise ValueError('passwords do not match')
        return v

3. Заключение

Подведем итоги тому, что мы узнали сегодня.

Мы начали с подробного объяснения Pydantic, который помогает анализировать и проверять данные.

Затем мы создали виртуальную среду и установили Pydantic через pip или conda. Он также включает поддержку трех дополнительных зависимостей на основе наших сценариев использования.

Когда мы закончили установку, мы подробно изучили основные функции, предоставляемые пакетом. Базовым строительным блоком является создание нового класса, унаследованного от BaseModel.

Мы узнали, что Pydantic обеспечивает поддержку большинства распространенных типов данных в стандартной библиотеке Python. Мы протестировали как Constrained Types, так и Strict Types, которые помогают обеспечить соблюдение наших собственных ограничений.

Наконец, вы поигрались с декоратором validator, чтобы разрешить ввод только четырех цифр для id, а confirm_password должен соответствовать полю password.

Спасибо, что прочитали эту статью. Надеюсь увидеть вас снова в следующей статье!

Ссылка

  1. Страница Pydantic Github
  2. Пидантическая документация