Как динамически совместно использовать переменную конфигурации для всего пакета?

#python #configuration #python-module #python-packaging

Вопрос:

Я создаю пакет python, в котором есть модуль под названием «конфигурация», в котором я определил различные файлы, содержащие некоторые глобальные переменные, которые используются в качестве конфигурации в других модулях.

 .
└── mypackage
    ├── base.py
    ├── config
    │   ├── completion.py
    │   ├── __init__.py
    │   ├── locals.py
    │   └── queries.py
    ├── encoders.py
    ├── exceptions.py
    ├── functions
    │   ├── actions.py
    │   ├── dummy.py
    │   ├── __init__.py
    │   ├── parsers.py
    │   └── seekers.py
    ├── __init__.py
    ├── query.py
    └── utils
        ├── dict.py
        ├── __init__.py
        └── retry.py
 

Например, файл mypackage/config/queries.py содержит следующее содержимое:

 INCLUDE_PARENTS = False
 

В то время как в основном файле mypackage/base.py у меня есть функция , которая принимает эту переменную конфигурации в качестве аргумента по умолчанию:

 import mypackage.config.queries as conf

def query(include_parent_=conf.INCLUDE_PARENTS, **kwargs):
    # do stuff depending on include_parent_ argument
 

Чего я хочу и чего я не смог найти в других подобных вопросах, так это иметь возможность динамически изменять эти переменные в сеансе консоли Python/Ipython. То есть я должен быть в состоянии сделать следующее на Ipython:

 In [1]: import mypackage as mp

In [2]: mp.config.INCLUDE_PARENTS = True # Its default value was False

In [3]: mp.query()
Out[3]: # result with include_parent_ argument set to True

In [4]: mp.config.INCLUDE_PARENTS = False # Now I set the value back to False

In [5]: mp.query()
Out[5]: # result with include_parent_ argument set to False
 

Но я не понимаю, почему я не могу этого достичь. Я попытался импортировать переменные конфигурации в init.py с их связанным пространством имен, но мне никогда не удается динамически изменять глобальные переменные конфигурации, как это делает, например, Pandas.

Ответ №1:

Проблема в том, что вы используете conf.INCLUDE_PARENTS функцию в качестве параметра по умолчанию. Параметр по умолчанию вычисляется при создании функции, а не при ее вызове. Таким образом, при последующем изменении кода значение внутри функции не меняется. Следующее должно работать так, как вы ожидаете.

 def query(include_parent_=None, **kwargs):
    if include_parent_ is None:
        include_parent_ = conf.INCLUDE_PARENTS
    # do stuff depending on include_parent_ argument