Importing a long list of constants to a Python file
Asked Answered
A

12

130

In Python, is there an analogue of the C preprocessor statement such as?:

#define MY_CONSTANT 50

Also, I have a large list of constants I'd like to import to several classes. Is there an analogue of declaring the constants as a long sequence of statements like the above in a .py file and importing it to another .py file?

Edit.

The file Constants.py reads:

#!/usr/bin/env python
# encoding: utf-8
"""
Constants.py
"""

MY_CONSTANT_ONE = 50
MY_CONSTANT_TWO = 51

And myExample.py reads:

#!/usr/bin/env python
# encoding: utf-8
"""
myExample.py
"""

import sys
import os

import Constants

class myExample:
    def __init__(self):
        self.someValueOne = Constants.MY_CONSTANT_ONE + 1
        self.someValueTwo = Constants.MY_CONSTANT_TWO + 1

if __name__ == '__main__':
    x = MyClass()

Edit.

From the compiler,

NameError: "global name 'MY_CONSTANT_ONE' is not defined"

function init in myExample at line 13 self.someValueOne = Constants.MY_CONSTANT_ONE + 1 copy output Program exited with code #1 after 0.06 seconds.

Aguila answered 14/6, 2011 at 12:17 Comment(3)
No, there is no preprocessor. And no, you won't get very far trying to code C in Python, or even trying to find parallels.Kuykendall
That's not the full traceback. How you're running it? python myExample.py should give a traceback on error that includes file names and <module> as top level. Plus, MY_CONSTANT_ONE isn't references as a global name - really weird. Triple-check that those are really the files you're running (and perhaps convert them to ASCII and strip the # encoding: utf8 bit).Kuykendall
@All: Thanks, I seem to be fine now - not yet sure why, but never mind :).Aguila
Q
190

Python isn't preprocessed. You can just create a file myconstants.py:

MY_CONSTANT = 50

And importing them will just work:

import myconstants
print myconstants.MY_CONSTANT * 2
Questioning answered 14/6, 2011 at 12:23 Comment(13)
@SK9: Well, show the exact code you're running (both defining and using module).Kuykendall
@Thomas: See above. I've definitely missed something daft some where as I'm learning the basics.Aguila
@SK9: There is no such error in the code you posted. I checked it several times and run it myself, it works just fine. It can't even lead to this error (there's no reference to a name MAX_FIVE_FLUSH_KEY_INT). Post the traceback.Kuykendall
@Thomas: Thanks for testing this. Hmm, I'll try again. (The reference alluded to is a typo.) You tried the files literally as is? (I copied and pasted the full contents above.)Aguila
@SK9: I'm not Thomas ;) And yes, I copied and pasted everything, I even left the filenames as they are. Again, the traceback would help us debugging.Kuykendall
@delnan: Thanks ;) What I have from the log is now posted above.Aguila
@SK9: you have a file called myConstants.py, but you import the module Constants? If you didn't get an ImportError, you either have multiple versions of files around or you're not posting what you actually ran.Steib
@DSM: The docstring of the file itself says Constants.py though. And even if that was the case, that still wouldn't explain why and how it thinks the MY_CONSTANT_ONE in Constants.MY_CONSTANT_ONE was a global name.Kuykendall
@DSM: Yes it should be "Constants.py" (I have that in my code etc.) so that's not it. Hmm.Aguila
@delnan: docstrings don't change the module name, and I was wondering if it was a different version of the code which was being imported, which might be doing something weird. I can't explain the error message, though.Steib
Okay, this is insane, but is it possible that periods and commas have been swapped somehow? This is exactly the error message you'd get if that were true!Steib
@delnan, @Steib : Thanks for fielding on this one. I have my browser block SO during working hours, to discourage procrastination.Questioning
Be sure not to use '-' in module names. Use '_' instead - causes issues with thing like from <module name> import constAeroplane
K
25

Python doesn't have a preprocessor, nor does it have constants in the sense that they can't be changed - you can always change (nearly, you can emulate constant object properties, but doing this for the sake of constant-ness is rarely done and not considered useful) everything. When defining a constant, we define a name that's upper-case-with-underscores and call it a day - "We're all consenting adults here", no sane man would change a constant. Unless of course he has very good reasons and knows exactly what he's doing, in which case you can't (and propably shouldn't) stop him either way.

But of course you can define a module-level name with a value and use it in another module. This isn't specific to constants or anything, read up on the module system.

# a.py
MY_CONSTANT = ...

# b.py
import a
print a.MY_CONSTANT
Kuykendall answered 14/6, 2011 at 12:24 Comment(0)
S
17

And ofcourse you can do:

# a.py
MY_CONSTANT = ...

# b.py
from a import *
print MY_CONSTANT
Septempartite answered 14/6, 2011 at 12:33 Comment(4)
import * is of the devil.Kuykendall
import * is discouraged in general, but C-style manifest constants that are widely used across a codebase are one of the places where it's not insane to use it. Naming them in ALL_CAPS or with some prefix convention that reduces the possibility of collision with other symbols removes the main objection to the idiom, and if a collision does occur you can always fall back to the conventional import + explicit name style (import a; a.MY_CONSTNAT), unlike in C.Busywork
also a.MY_CONSTNAT a little slower, that's because interpreter looking in one namespace for name 'a' and then in second one foe name 'MY_CONSTNAT'Septempartite
I personally use import * a lot, and it werks out well enough.Hasseman
P
8

Sure, you can put your constants into a separate module. For example:

const.py:

A = 12
B = 'abc'
C = 1.2

main.py:

import const

print const.A, const.B, const.C

Note that as declared above, A, B and C are variables, i.e. can be changed at run time.

Pownall answered 14/6, 2011 at 12:24 Comment(0)
G
7

Try to look Create constants using a "settings" module? and Can I prevent modifying an object in Python?

Another one useful link: http://code.activestate.com/recipes/65207-constants-in-python/ tells us about the following option:

from copy import deepcopy

class const(object):

    def __setattr__(self, name, value):
        if self.__dict__.has_key(name):
            print 'NO WAY this is a const' # put here anything you want(throw exc and etc)
            return deepcopy(self.__dict__[name])
        self.__dict__[name] = value

    def __getattr__(self, name, value):
        if self.__dict__.has_key(name):
            return deepcopy(self.__dict__[name])

    def __delattr__(self, item):
        if self.__dict__.has_key(item):
            print 'NOOOOO' # throw exception if needed

CONST = const()
CONST.Constant1 = 111
CONST.Constant1 = 12
print a.Constant1 # 111
CONST.Constant2 = 'tst'
CONST.Constant2 = 'tst1'
print a.Constant2 # 'tst'

So you could create a class like this and then import it from you contants.py module. This will allow you to be sure that value would not be changed, deleted.

Galton answered 14/6, 2011 at 12:48 Comment(2)
Thanks for this. Before asking on SO I searched and found both of these. :)Aguila
@SK9 oh, sorry for duplicate thenGalton
M
5

As an alternative to using the import approach described in several answers, have a look a the configparser module.

The ConfigParser class implements a basic configuration file parser language which provides a structure similar to what you would find on Microsoft Windows INI files. You can use this to write Python programs which can be customized by end users easily.

Maestoso answered 14/6, 2011 at 12:43 Comment(0)
Z
4

create constant file with any name like my_constants.py declare constant like that

CONSTANT_NAME = "SOME VALUE"

For accessing constant in your code import file like that

import my_constants as constant

and access the constant value as -

constant.CONSTANT_NAME
Zootoxin answered 14/1, 2020 at 16:2 Comment(0)
C
2

If you really want constants, not just variables looking like constants, the standard way to do it is to use immutable dictionaries. Unfortunately it's not built-in yet, so you have to use third party recipes (like this one or that one).

Credulity answered 14/6, 2011 at 12:44 Comment(0)
C
0

In commercial software, the constant(s) will frequently be buried many folders deep. Use solution below in combination with above solutions for best results. Here's the syntax that worked for me:

folder_a
    folder_b
        constants.py
# -----------
# constants.py
# ------------
MAXVAL = 1000

folder_c
    folder_d
        my_file.py

# ------------------------
# my_file.py
# ------------------------
import folder_a.folder_b.constants as consts

print(consts.MAXVAL)
Crimmer answered 26/3, 2021 at 18:52 Comment(0)
F
0

In more recent editions, it seems a bit pickier.

the mode in the top answer

Main.py

import constants
print(token)

constants.py enter code heretoken = "12345"

failed. Instead, I had to import individual variable from constants.

Main.py

from constants import token
print(token)
Freida answered 9/2, 2022 at 1:37 Comment(0)
B
0

A constants.py file is good, but I ran into a situation where I would rather had my constants on top of the file.

A similar Python dict would need an access to the variable with a string key dict['A'], but I needed something with the same syntax as a module import.

(For the curious, I was working on Google Collab .ipynb multiple files, with different configuration variables for each of them, and you can't edit quickly an imported constants.py from Collab, nor import directly another .ipynb file. )

from dataclasses import dataclass

@dataclass
class Constants:
    A = "foo"

cst = Constants()
print(cst.A)
>>> "foo"

You could also create a classic Python Class, but this needs to define a __init__

Bonnibelle answered 1/6, 2022 at 8:45 Comment(0)
K
0

This is my solution:

Asum Directory structure

project
|-- package1
|   |-- param1.py
|
|-- package2
|   |-- somefile.py
|
|-- main.py
|-- param2.py

param1.py

MY_CONST = 'abc'

param2.py

MY_CONST = 'xyz'

somefile.py

from package1 import param1

my_var = "inside some file " + param1.MY_CONST

main.py

from package1 import param1
import param2
from package2 import somefile

print(param1.MY_CONST)
print(param2.MY_CONST)
print(somefile.my_var)

Run main.py

Result:

abc
xyz
inside some file abc

As you can see, you can use const from another package. Hope this helps others!!

Kaifeng answered 1/1, 2023 at 21:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.