项目的python设置-循环导入/依赖项注入

时间:2019-03-27 10:08:03

标签: python dependency-injection settings python-import

我为不同的环境创建了“ Django风格”设置文件。 设置文件定义了一些变量,还用作其他模块的依赖项注入。

所以结构是:

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.pyservice_mock.py导入了一个类。
这通常可以正常工作。

现在,问题在于service.py无法导入设置包,因为设置文件导入了service.py,因此将变成循环导入。

正如我在Django中看到的那样,这是通过在设置文件中使用导入字符串而不是实际导入来解决的。 我真的不喜欢这个想法,因为我失去了一些IDE自动完成功能,而且我不确定如何实际创建Django提供的设置对象。

该问题有哪些解决方案?是否有一个设置文件用作导入模块的依赖项注入容器,并由相同的模块导入?最好是一个简单的解决方案。

2 个答案:

答案 0 :(得分:4)

循环进口的一种非常普遍且肯定是最简单的解决方案是将进口推迟到您真正需要它们之前。例如,更改

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()

(或泛化为任何模块名称)

答案 1 :(得分:0)

代替:

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