Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't Flask can't see my environment variables from Apache (mod_wsgi)?

I want to pass in environment variables through Apache + mod_wsgi to tell my app whether it's running in a development or production environment. (This needs to happen when the app is launched, before any requests have come in.) For example:

<VirtualHost *:80>
    ...
    SetEnv ENVTYPE production
    WSGIScriptAlias /myapp  /apps/www/80/wsgi-scripts/myapp/run.py
</VirtualHost>
<VirtualHost *:8080>
    ...
    SetEnv ENVTYPE development
    WSGIScriptAlias /myapp  /apps/www/80/wsgi-scripts/myapp/run.py
</VirtualHost>

Based on the answer given to "Apache SetEnv not working as expected with mod_wsgi", I have setup run.py and the main __init__.py like this:

Old run.py:

from myapp import app as application

if __name__ == '__main__':
    application.run(debug=True, threaded=True)

New run.py :

import os
from myapp import app as _application

def application(environ, start_response):
    os.environ['ENVTYPE'] = environ['ENVTYPE']
    return _application(environ, start_response)

if __name__ == '__main__':
    _application.run(debug=True, threaded=True)

__init__.py

app = Flask(__name__)
app.config.from_object(__name__)
if os.environ.get('ENVTYPE') == 'production'
    # Setup DB and other stuff for prod environment
else:
    # Setup DB and other stuff for dev environment

Two problems

  1. This does not actually work. Within __init__.py, there is no 'ENVTYPE' key in os.envrion. Why not?

  2. I also don't know how to fix the if __name__ == '__main__' section so that I can run run.py as a local Flask app on my PC. What I put in my new run.py works, but only by calling _application instead of the wrapper function application. As a result _application doesn't have access to the environment variables I defined. How can I fix that line?

Thank you!

like image 844
George Adams Avatar asked Jul 14 '16 21:07

George Adams


1 Answers

I solved problem #1 thanks to this tip

Note that the Flask app is imported inside the def application block — if you import it outside of this block, you won't be able to use the environment variables at the Flask app level or any file which is imported on application load. This is because the WSGI application hasn't loaded at the time you import the Flask application, so it can't pass the environment variables yet.

So the working version of run.py is:

import os

def application(environ, start_response):
    os.environ['ENVTYPE'] = environ['ENVTYPE']
    from myapp import app as _application
    return _application(environ, start_response)

if __name__ == '__main__':
    _application.run(debug=True, threaded=True)

I still haven't solved problem #2, however - I don't know how to call the program directly (if __name__ == '__main__') and have access to the ENVTYPE environment variable. Suggestions would still be appreciated. Maybe I'll break that issues out into its own StackOverflow question.

like image 108
George Adams Avatar answered Sep 29 '22 01:09

George Adams