Следующее решение предлагает как приведение во время выполнения к нужным типам , так и подсказки подсказок типа редактором без использования внешних зависимостей .
Также проверьте ответ kederra c , чтобы найти отличную альтернативу, используя pydantic
, которая позаботится обо всем этом для вас.
Работа напрямую с файлом не-1076 * dotenv будет слишком сложной, если не невозможной. Намного проще обрабатывать всю информацию в некоторой Python структуре данных, поскольку это позволяет средствам проверки типов выполнять свою работу без каких-либо изменений.
Я думаю, что путь к go состоит в использовании Python классы данных . Обратите внимание, что хотя мы указываем типы в определении, они только для контролеров типов, не применяются во время выполнения . Это проблема для переменных среды, поскольку они в основном являются внешней string
отображаемой информацией. Чтобы преодолеть это, мы можем форсировать приведение в методе __post_init__
.
Реализация
Во-первых, по причинам организации кода мы можем создать Mixin с типом логики c. Обратите внимание, что случай bool
является особенным, поскольку его конструктор выведет True
для любой непустой строки, включая "False"
. Если есть какой-то другой не встроенный тип, который вы хотите обработать, вам также потребуется добавить для него специальную обработку (хотя я бы не советовал делать так, чтобы этот logi c обрабатывал больше, чем эти простые типы).
import dataclasses
from distutils.util import strtobool
class EnforcedDataclassMixin:
def __post_init__(self):
# Enforce types at runtime
for field in dataclasses.fields(self):
value = getattr(self, field.name)
# Special case handling, since bool('False') is True
if field.type == bool:
value = strtobool(value)
setattr(self, field.name, field.type(value))
Эту реализацию также можно выполнить с помощью декоратора, см. здесь .
Затем мы можем создать эквивалент файла ".env.example
", например:
import dataclasses
@dataclasses.dataclass
class EnvironmentVariables(EnforcedDataclassMixin):
SSL: bool
PORT: int
DOMAIN: str
и для простого анализа из os.environ
мы можем создать функцию, такую как
from typing import Mapping
def get_config_from_map(environment_map: Mapping) -> EnvironmentVariables:
field_names = [field.name for field in dataclasses.fields(EnvironmentVariables)]
# We need to ignore the extra keys in the environment,
# otherwise the dataclass construction will fail.
env_vars = {
key: value for key, value in environment_map.items() if key in field_names
}
return EnvironmentVariables(**env_vars)
Использование
Наконец, взяв эти вещи вместе, мы можем написать в файле настроек:
import os
from env_description import get_config_from_map
env_vars = get_config_from_map(os.environ)
if 65535 < env_vars.PORT:
print("Invalid port!")
if not env_vars.SSL:
print("Connecting w/o SSL!")
Stati c проверка типов работает правильно в VS Code и mypy. Если вы назначите PORT
(то есть int
) переменной типа str
, вы получите предупреждение!
![Type hinting working](https://i.stack.imgur.com/yLFq0.png)
Чтобы сделать вид, что это словарь, Python предоставляет метод asdict
в модуле dataclasses
.
env_vars_dict = dataclasses.asdict(env_vars)
if 65535 < env_vars_dict['PORT']:
print("Invalid port!")
Но, к сожалению (на момент этого ответа) вы теряете проверку типа stati c Поддержите это. Кажется, для mypy работа в процессе .