настройки Python для проекта - циклический импорт / внедрение зависимостей - PullRequest
3 голосов
/ 27 марта 2019

Я создал файлы настроек 'Django style' для разных сред.Файлы настроек определяют некоторые переменные, а также служат для внедрения зависимостей для других модулей.

Итак, структура:

settings/
    ___init__.py
    base.py
    dev.py
    dev2.py
    prod.py

service/
    __init__.py
    service.py
    service_mock.py

А в settings/__init__.py я пишу:

settings_env = os.environ.get('PROJECT_SETTINGS', '')
if settings_env == 'prod':
   from .prod import *
elif settings_env == 'dev':
   from .dev import *

Каждый файл настроек определяет различные переменные, а также импортирует класс из service.py или service_mock.py, в зависимости от переменной среды.
Это работает в основном нормально.

Теперь проблема в том, что service.py не может импортировать пакет настроек, потому что файлы настроек импортируют service.py, так что импорт станет циклическим.

Как я вижу вDjango это решается с помощью импорта строк в файлах настроек, вместо фактического импорта.Мне не очень нравится эта идея, поскольку я теряю некоторые функции автозаполнения IDE, а также я не уверен, как на самом деле создать объект настроек, предоставляемый Django.

Каковы решения этой проблемы?Наличие файла настроек, который служит контейнером внедрения зависимостей, который импортирует модули и импортируется теми же модулями?Желательно простое решение.

Ответы [ 2 ]

4 голосов
/ 31 марта 2019

Очень распространенное и, безусловно, самое простое решение для кругового импорта - отложить импорт до тех пор, пока он вам действительно не понадобится. Например, изменить

import settings
def func():
    settings.things

до

def func():
    import settings
    settings.things

Если вам абсолютно необходимо импортировать модуль в глобальном масштабе, вы можете использовать различные приемы, например

settings = None
def import_stuff():
    global settings
    import settings as s
    settings = s

или есть класс

class Settings():
    mod = None        

    def __getattr__(self, attr):
        if self.mod is None:
            import settings
            self.mod = settings
        return getattr(self.mod, attr)

settings = Settings()

(или обобщить для любого имени модуля)

0 голосов
/ 06 апреля 2019

Вместо:

settings_env = os.environ.get('PROJECT_SETTINGS', '')
if settings_env == 'prod':
   from .prod import *
elif settings_env == 'dev':
   from .dev import *

Вы можете просто экспортировать переменную:

DJANGO_SETTINGS_MODULE your_project.settings.dev2

и Django прочитает нужный файл.

Также: Вместо

import settings

вы хотели бы использовать:

from django.conf import settings

и выше могут быть вложены в методы / функции, чтобы избежать циклического импорта.

см .: https://docs.djangoproject.com/en/dev/topics/settings/#using-settings-in-python-code

см .: https://docs.djangoproject.com/en/dev/topics/settings/#custom-default-settings

...