1

I currently have a small list (< 20) of constants that can be segmented into the following three parts:

- main script (tokens, log file location)
- database setup (username, passwords)
- API (API key, various external IDs)

I felt that it cluttered the top of the files during declaration, so I transferred them into a constants file. However, when importing them back to the three files, for instance say the database setup, it would become

import constants

...

db = connect(constants.RDS_HOSTNAME, constants.RDS_PASSWORD)

compared to if I had declared them in the file

RDS_HOSTNAME = 'xxx'
RDS_PASSWORD = 'yyy'

...

db = connect(RDS_HOSTNAME, RDS_PASSWORD)

which I feel is a bit more readable when using the constants.

If I combine the both, I would have

from constants import *

...

db = connect(RDS_HOSTNAME, RDS_PASSWORD)

but all posts I've read suggest very heavily against this as it would increase confusion due to not knowing where the constants come from.

My question is this: given that I have only one constants file with no functions, and all constants are upper case, would using from constants import * nonetheless be poor practice? Due to the uppercase notation, I would know immediately it's a constant and comes from the constants file, thus reducing confusion.

2

All the “constants” you listed have nothing to do in your code. They belong to the configuration.

Think it this way. Your code contains the logic. Whenever you change the logic, you change your code. Whenever you change information about the world, you don't change your code.

If this is still unclear, think about somebody taking your code and running it in a very different context. For instance you created a bulletin board system and you run it on your local server, connecting to the specific PostgreSQL database and using Amazon S3 to store uploaded files. You published the source code on GitHub, which allows me to grab the code and run it on my own infrastructure, using my own PostgreSQL database and my own S3 bucket (you won't enjoy paying Amazon to let me store this data in your bucket, do you?) Therefore, GitHub will contain the logic; configuration files, on the other hand, would be kept private on your servers, and should never reach GitHub (unless you really want people to use your S3 bucket for free).

API keys, passwords and log file locations should therefore be in configuration files, and constants should be kept for things which are constant within the scope of your logic. If, say, your logic forces you to have specific types of users, for instance administrators—designed as Administrator in your code, ordinary users—Contributor, and finally anonymous users—Guest, then Administrator, Contributor and Guest are the constants, because they are part of your business logic. In this case, you'll put them in the file in which they belong, possibly in or near the class which represents the user or more specifically the type of the user.

  • Thanks for the reply! I have a quick followup: suppose instead of hard-coding the credentials, I have them read from a file or imported from environment variables. In that case, would it be better to abstract away where the configs come from (via file or env) by a config, or leave them be in the script that they'll be used? – user154989 Feb 8 at 21:15
  • 1
    Stick with the tools provided the framework you use. Unless you have very specific requirements, the default tool will do the job, and you won't even need to ask yourself how should you access the configuration. – Arseni Mourzenko Feb 8 at 21:23
  • A separate file can also help prevent circular dependencies, same as a separate errors.py file. Also, you can just as well import it as from .constants import RDS_HOSTNAME or alias constants to a shorter name – Tjorriemorrie Feb 11 at 22:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.