183

I want to define a constant that should be available in all of the submodules of a package. I've thought that the best place would be in in the __init__.py file of the root package. But I don't know how to do this. Suppose I have a few subpackages and each with several modules. How can I access that variable from these modules?

Of course, if this is totally wrong, and there is a better alternative, I'd like to know it.

pmav99
  • 1,909
  • 2
  • 20
  • 27
Andrei Vajna II
  • 4,642
  • 5
  • 35
  • 38

4 Answers4

268

You should be able to put them in __init__.py. This is done all the time.

mypackage/__init__.py:

MY_CONSTANT = 42

mypackage/mymodule.py:

from mypackage import MY_CONSTANT
print "my constant is", MY_CONSTANT

Then, import mymodule:

>>> from mypackage import mymodule
my constant is 42

Still, if you do have constants, it would be reasonable (best practices, probably) to put them in a separate module (constants.py, config.py, ...) and then if you want them in the package namespace, import them.

mypackage/__init__.py:

from mypackage.constants import *

Still, this doesn't automatically include the constants in the namespaces of the package modules. Each of the modules in the package will still have to import constants explicitly either from mypackage or from mypackage.constants.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
Jason R. Coombs
  • 41,115
  • 10
  • 83
  • 93
  • 24
    This should have been the accepted answer. If you are working with Python 2.5 or higher you can also use an explicit relative import as well as described [here](http://docs.python.org/2/tutorial/modules.html#intra-package-references): `from . import MY_CONSTANT` – ThatAintWorking Feb 12 '14 at 17:17
  • doesn't the second way only work for constants? `from mypackage.constants import *` will place copies of `MY_CONSTANT` in every submodule rather than a reference to the same variable – hardmooth Mar 18 '16 at 07:17
  • @hardmooth: Not exactly. The values are copied by reference, so if you were to mutate `MY_CONSTANT` in any of the modules, it would mutate everywhere. If you were to re-assign `MY_CONSTANT` in any of the modules, it would only affect that module. If that's your intention, you must reference by attribute, i.e. `mypackage.constants.MY_CONSTANT`. – Jason R. Coombs Mar 23 '16 at 14:05
  • 12
    One catch with the example is if you import `mymodule.py` in `__init__.py` before `MY_CONSTANT = 42` that will fail because when importing `mymodule.py` `MY_CONSTANT` hasn't been defined yet. So need to move `MY_CONSTANT = 42` above `import mymodule` – markmnl Nov 16 '17 at 05:30
  • how is about variable? It's asking about variables, not constants. How python treats variable inside package? What If variable inside package has been changed? – TomSawyer Dec 22 '17 at 20:13
34

You cannot do that. You will have to explicitely import your constants into each individual module's namespace. The best way to achieve this is to define your constants in a "config" module and import it everywhere you require it:

# mypackage/config.py
MY_CONST = 17

# mypackage/main.py
from mypackage.config import *
Ferdinand Beyer
  • 64,979
  • 15
  • 154
  • 145
  • Yeah, a configuration file is what I would like. I just thought that __init__.py would be a good place. Your solution sounds like standard practice. Is it? – Andrei Vajna II Sep 05 '09 at 12:42
  • 1
    Good point. I didn't realize the question was to have the constants _automatically_ placed in the namespace of all package modules. – Jason R. Coombs Sep 05 '09 at 13:00
  • 1
    But every time a script imports config.py, the code inside is executed. What do you recommend if the code inside config.py is to be run only once? Say I'm reading a settings.json file inside config.py and I don't want to open() it every time I import config.py. – Augiwan Jul 03 '14 at 08:12
  • 1
    @UGS This is not how Python works. Every module is executed only once. When it is imported the second time, the module is already cached in `sys.modules`. – Ferdinand Beyer Jul 03 '14 at 08:38
  • @FerdinandBeyer Oops! I forgot to mention that I'm importing config.py from several scripts and not the same script. Say a.py is importing config.py & b.py and b.py is importing config.py. I was wondering if its possible to make sure code inside config.py is executed only once. – Augiwan Jul 03 '14 at 08:43
  • @UGS You don't understand. It does not matter which other module/script is importing a module or how many times. A module is always only loaded once (unless a reload is forced with `reload`). If `a.py`, `b.py` and `c.py` all `import shared`, `shared.py` is executed exactly once. The second and third `import`s get the already loaded module object. – Ferdinand Beyer Jul 03 '14 at 11:07
  • This is incorrect. The code in `shared.py` is executed each time a script imports it in its own session. However, if the scripts are called from the same session, then the code is exectuted only once - but I've already mentioned that this is not the case. I did some reading and the solution is to use a caching mechanism(like memcached) or persist to a file which defeats the purpose of my initial question(which is to avoid reading a file each time). – Augiwan Jul 03 '14 at 12:38
  • 1
    So why is this way better than putting global constants under __init__.py and then directly do `from mypackage import *`? – Yu Gu Nov 17 '19 at 03:27
2

You can define global variables from anywhere, but it is a really bad idea. import the __builtin__ module and modify or add attributes to this modules, and suddenly you have new builtin constants or functions. In fact, when my application installs gettext, I get the _() function in all my modules, without importing anything. So this is possible, but of course only for Application-type projects, not for reusable packages or modules.

And I guess no one would recommend this practice anyway. What's wrong with a namespace? Said application has the version module, so that I have "global" variables available like version.VERSION, version.PACKAGE_NAME etc.

u0b34a0f6ae
  • 48,117
  • 14
  • 92
  • 101
-1

Just wanted to add that constants can be employed using a config.ini file and parsed in the script using the configparser library. This way you could have constants for multiple circumstances. For instance if you had parameter constants for two separate url requests just label them like so:

mymodule/config.ini
[request0]
conn = 'admin@localhost'
pass = 'admin'
...

[request1]
conn = 'barney@localhost'
pass = 'dinosaur'
...

I found the documentation on the Python website very helpful. I am not sure if there are any differences between Python 2 and 3 so here are the links to both:

For Python 3: https://docs.python.org/3/library/configparser.html#module-configparser

For Python 2: https://docs.python.org/2/library/configparser.html#module-configparser

Dan Temkin
  • 1,565
  • 1
  • 14
  • 18