9

what is the pythonic way to use a config in object oriented programming?

I thought of the following 2 setups:

class Main():
    def __init__(self):
        self.config = ConfigClass("config_file.cfg")
        self.worker = WorkerClass(self.config.USER_NAME)
        self.worker2 = WorkerClass2(self.config)

    def run(self):
        self.worker.work()
        self.worker2.work()

class ConfigClass():
    def __init__(self, file_name):
        self.config = ConfigParser.ConfigParser()
        self.config.read(file_name)

    @property
    def USER_NAME(self):
        return self.config.get("USER", "NAME")

class WorkerClass():
    def __init__(self, user_name):
        self.user = user_name

    def work(self):
        print(self.user)

class WorkerClass2():
    def __init__(self, config):
        self.config = config
        self.user = self.config.USER_NAME

    def work(self):
        print(self.user)

Is it preferred to pass the config object or just the needed strings or is there a better different approach which I didn't mention?

Thanks in advance.

F.M.F.
  • 1,929
  • 3
  • 23
  • 42

1 Answers1

4

in flask we have the factory pattern to initialize the app in simple and flexible ways between diff environment. using python-dotenv package, allow to you to load variable in a .env file which will be unique for each environment (dev, staging, prod...). you can use the same pattern.

here is an example of .env file locally, and you want to use diff databases for diff purposes (dev, testing ...)

DATABASE_URI=postgresql://exercise_user:pass@127.0.0.1:5432/exercise_new_db
DATABASE_TEST_URI=postgresql://exercise_user:pass@127.0.0.1:5432/exercise_db_test
DATABASE_DOCKER_URI=postgresql://docker_exercise_user:pass@db/docker_exercise_db

to let the software know which environment is running on, write a shell start.sh script that will export the main environment variable

export ENV=development
python main.py

and here is an example of config file, where you define an abstract class contains all configurations that are the same for all envs, then you create for each environemnt a class inherited from that base class, and these class contains unique configuration.

from os import environ, path
from dotenv import load_dotenv, find_dotenv


basedir = path.abspath(path.dirname(__file__))
# here we we load environment variables from .env, must be called before init. class
load_dotenv(find_dotenv(), verbose=True)


class ConfigFactory(object):
    def factory():
        env = environ.get("ENV", "development")
        if env is 'testing':
            return Testing()
        elif env is 'development':
            return Development()
        elif env is 'docker':
            return Docker()
        elif env is 'production':
            return Production()


class Config:

    """Base config."""
    SQLALCHEMY_TRACK_MODIFICATIONS = False


class Development(Config):
    DEBUG = True
    TESTING = False
    SQLALCHEMY_DATABASE_URI = environ.get('DATABASE_URI')


class Testing(Config):
    DEBUG = True
    TESTING = True
    SQLALCHEMY_DATABASE_URI = environ.get('DATABASE_TEST_URI')


class Docker(Config):
    DEBUG = True
    TESTING = False
    SQLALCHEMY_DATABASE_URI = environ.get('DATABASE_DOCKER_URI')


class Production(Config):
    DEBUG = True
    TESTING = False
    SQLALCHEMY_DATABASE_URI = environ.get('DATABASE_URI')

and finally you import you config class in your main file and call it

alim91
  • 538
  • 1
  • 8
  • 17