Python печатание - есть ли способ избежать импорта необязательного типа, если его нет? - PullRequest
3 голосов
/ 11 марта 2020

Допустим, у нас есть определение функции, подобное этому:

def f(*, model: Optional[Type[pydantic.BaseModel]] = None)

Таким образом, функция не требует установки pydantic, пока вы не передадите что-то как model. Теперь предположим, что мы хотим упаковать функцию в пакет pypi. И мой вопрос: есть ли способ избежать включения pydantic в зависимости пакета только ради проверки типов?

Ответы [ 3 ]

4 голосов
/ 11 марта 2020

Я пытался следовать совету dspenser , но обнаружил, что mypy по-прежнему дает мне Name 'pydantic' is not defined ошибку. Затем я нашел эту главу в документации , и, похоже, она работает и в моем случае:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    import pydantic

Вы можете использовать обычные выражения (вместо строковых литералов) с __future__.annotations ( python 3.8.1):

from __future__ import annotations

from typing import TYPE_CHECKING, Optional, Type

if TYPE_CHECKING:
    import pydantic


def f(*, model: Optional[Type[pydantic.BaseModel]] = None):
    pass

Если по какой-то причине вы не можете использовать __future__.annotations, например, если вы используете python <3.7, используйте ввод со строковыми литералами из <a href="https://stackoverflow.com/a/60632600/3694363"> раствор Дпенсера .

3 голосов
/ 11 марта 2020

Python Модуль typing может использовать имена строковых типов, а также сам тип, как у вас в примере.

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

def f(*, model: Optional[Type["pydantic.BaseModel"]] = None)

Ваша проверка типа stati c с использованием mypy должна продолжать работать, но ваш пакет больше не всегда будет нуждаться в зависимости от pydantic.

Как вы обнаружили в документах , в модуле python *1031* есть способ указать, что некоторые операции импорта требуются только для (строкового литерала) аннотаций типа:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    import pydantic

Это будет выполнять оператор import pydantic только тогда, когда TYPE_CHECKING равен True, главным образом при использовании mypy для анализа типов в коде. При нормальном запуске программы оператор импорта не выполняется. По этой причине опция должна использоваться только с подсказками строкового литерала; в противном случае отсутствующий импорт приведет к сбою нормального выполнения программы.

Поскольку ленивая оценка подсказок типа должна быть реализована в Python 4.0,

from __future__ import annotations

можно использовать для включения этого поведения в Python 3. С этим оператором импорта типы строковых литералов не требуются.

0 голосов
/ 11 марта 2020

Я бы сделал что-то вроде

try:
    from pydantic import BaseModel as PydanticBaseModel
except ImportError:
    PydanticBaseModel = None

Не думаю, что это лучше, чем то, что предложил dspencer , но иногда какой-то странный гид по стилю может запретить вам использовать имена строковых типов, поэтому Я просто хотел указать другое решение.

...