-1

I have abstracted the reading of the .env file to settings.py but I'm not sure if this is idiomatic to python:

# .env 

SECRET=XXXX
# settings.py
import os
from os.path import join, dirname
from dotenv import load_dotenv

dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)

SECRET = os.environ.get("SECRET_KEY")
# app.py

from ..settings import CONSUMER_KEY

def useSecret(SECRET):

Should each module read the .env file directly?

timothyylim
  • 1,399
  • 2
  • 14
  • 32
  • 1
    `IO` is expensive, so `echo module reads .env file` definetly worse. – atline Sep 30 '21 at 11:14
  • How about writing a class that does a "lazy load" of the environment variables and which has its own *get()* method. In that way you'll only ever read the *env* file once –  Sep 30 '21 at 12:12
  • Hm, is there a standard way to read .env variables once and once only? – timothyylim Sep 30 '21 at 12:14

1 Answers1

0

This, in my opinion, is a case for using a singleton (which is slightly awkward in Python) but nonetheless you may find this useful.

from os.path import join, dirname
from os import environ
from dotenv import load_dotenv

DEBUG = True

class ENV():
    _instance = None
    _loaded = False
    _env = None
    def __new__(self):
        if self._instance is None:
            self._instance = super(ENV, self).__new__(self)
        return self._instance
    def load(self, env):
        if env != self._env:
            self._env = env
            self._loaded = False
        if not self._loaded:
            path = join(dirname(__file__), env)
            if DEBUG:
                print(f'Loading {path}')
            load_dotenv(path)
            self._loaded = True
        return environ
    def get(self, env, key):
        return self.load(env).get(key)


print(ENV().get('.env', 'SECRET_KEY'))
print(ENV().get('.env', 'SECRET_KEY'))

If you care to run this code as is (assuming you have a .env file with a SECRET_KEY key) then you'll see that load_dotenv is only called once