Skip to content

Instantly share code, notes, and snippets.

@bennylope
Last active August 17, 2023 10:44
Show Gist options
  • Star 47 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save bennylope/2999704 to your computer and use it in GitHub Desktop.
Save bennylope/2999704 to your computer and use it in GitHub Desktop.
Django manage.py file that loads environment variables from a .env file per Honcho/Foreman
Copyright the authors of Honcho and/or Ben Lopatin
Licensed for reuse, modification, and distribution under the terms of the MIT license
#!/usr/bin/env python
import os
import sys
import re
def read_env():
"""Pulled from Honcho code with minor updates, reads local default
environment variables from a .env file located in the project root
directory.
"""
try:
with open('.env') as f:
content = f.read()
except IOError:
content = ''
for line in content.splitlines():
m1 = re.match(r'\A([A-Za-z_0-9]+)=(.*)\Z', line)
if m1:
key, val = m1.group(1), m1.group(2)
m2 = re.match(r"\A'(.*)'\Z", val)
if m2:
val = m2.group(1)
m3 = re.match(r'\A"(.*)"\Z', val)
if m3:
val = re.sub(r'\\(.)', r'\1', m3.group(1))
os.environ.setdefault(key, val)
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project_name.settings")
from django.core.management import execute_from_command_line
read_env()
execute_from_command_line(sys.argv)
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project_name.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
@bennylope
Copy link
Author

See the blog post for more explanation of how and why.

This will read default environment variables from your local .env file, e.g.

DATABASE_URL='postgres://dbuser:dbpass@localhost/mydb'
DEBUG=False
FACEBOOK_APP_ID='51821095311150'
FACEBOOK_API_SECRET='fj43dfe897f612cf3448ce34f0f6ad1a1'

@AndrewJHart
Copy link

thx perfect for shell testing

@vegaro
Copy link

vegaro commented May 2, 2015

You saved my day, thanks!

@Flimm
Copy link

Flimm commented Oct 11, 2016

I like using this Python module: https://github.com/theskumar/python-dotenv

@kishorevbhosale
Copy link

nice one!

Copy link

ghost commented Feb 1, 2018

Why not just return instead of setting content = '' ?

@wanjalahenry
Copy link

Thank you!

@DrUChukwu
Copy link

thank you!

@seanballais
Copy link

seanballais commented Oct 15, 2019

This helped me a lot. Thanks! What license is this gist under?

@bennylope
Copy link
Author

This helped me a lot. Thanks! What license is this gist under?

Just added a LICENSE file with an MIT license. Have at it.

@simonseo
Copy link

Thanks! I have two questions.

Why do you remove a backslash character?
I'm not an expert with env variables and don't know of any case where there would be a backslash.

            m3 = re.match(r'\A"(.*)"\Z', val)
            if m3:
                val = re.sub(r'\\(.)', r'\1', m3.group(1))

Also as someone mentioned above,

Why not just return instead of setting content = '' ?

@simonseo
Copy link

I think it's worth noting (for people who won't read the blog post) that if you want to use Booleans in the .env file then you need to parse the string yourself. In the blog they use this function:

def env_var(key, default=None):
    """Retrieves env vars and makes Python boolean replacements"""
    val = os.environ.get(key, default)
    if val == 'True':
        val = True
    elif val == 'False':
        val = False
    return val

@perevertysh
Copy link

Hey! It not work, when you need use custom .env file in django app. It searches from .env file in django root settings directory.

@vicente-ramos
Copy link

Thank you very much!!!!
I change:
with open('.env') as f:
for
with open('path/to/.env') as f:
and works fantastic

@Scratchydisk
Copy link

Very useful, thanks.

I use honcho in some of my deployment scripts, so in that case I don't want the local .env file mucking things up.

I added a check before the "try" block that simply returns from read_env() if one of my environment variables is already set.

# Don't do anything if the environment is already loaded
# If YOUR_VARIABLE is defined then exit
if os.environ.get("YOUR_VARIABLE") is not None:
    print("Environment already loaded.  Ignoring .env")
    return

try:
    with open("../.env") as f:
        content = f.read()
except IOError:
    return`

Obviously replace YOUR_VARIABLE with, well, your variable!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment