Dani
Dani

Reputation: 544

How to dynamically share a package-wide config variable?

I am building a python package, which has a module called "config", in which I have defined different files that contain some global variables that are used as configuration in other modules.

.
└── 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

For example, the file mypackage/config/queries.py has the following content:

INCLUDE_PARENTS = False

Whereas in the main file mypackage/base.py, I have a function which takes this config variable as a default argument:

import mypackage.config.queries as conf

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

What I want, and what I haven't been able to find in other similar questions, is to be able to dynamically modify these variables in a Python/Ipython console session. That is, I should be able to do the following on 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

But I don't understand why I am not able to achieve it. I have tried importing the configuration variables in init.py with their associated namespace, but I never manage to be able to change the global configuration variables dynamically, as Pandas does, for example.

Upvotes: 2

Views: 227

Answers (1)

H. Rittich
H. Rittich

Reputation: 845

The issue is that you are using conf.INCLUDE_PARENTS as a default parameter of a function. A default parameter is evaluated when the function is created not when it is called. Thus, when you change your code later, the value inside the function does not change. The following should work as you expect.

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

Upvotes: 2

Related Questions