A question on app callables, WSGI servers and Flask circular imports
I am (possibly) confused. I want to safely create Flask / WSGI apps from app-factories and still be able to use them in WSGI servers easily.
tl;dr
Can I safely avoid creating an app on import of init (as recommended)and instead create it later (ie with a factory method)
How do I make that app work neatly with a WSGI server? Especially when I am passing in the config and other settings not pulling them from ENV
For example::
def make_app(configdict, appname):
app = Flask(appname)
app.config.update(configdict)
init_db(configdict)
set_app_in_global_namespace(app)
#importing now will allow from pkg import app
from mypackage import views
return app
I would like to use the above "factory", because I want to easily contorl config for testing etc.
I then presumably want to create a wsgi.py module that provides the app to a WSGI server.
So eventually things look a bit like this
init.py::
app = None
def make_app(configdict, appname):
flaskapp = Flask(appname)
flaskapp.config.update(configdict)
init_db(configdict)
global app
app = flaskapp
#importing now will allow from pkg import app
from mypackage import views
return flaskapp
wsgi.py::
from mypackage import app
app = make_app(configfromsomewhere, "myname")
uWSGI::
uwsgi --module=mypackage.wsgi:app
But still wsgi.py is NOT something I can call like wsgi.py --settings=x --host=10.0.0.1 So I don't really know how to pass the config in.
I am asking because while this seems ... OK ... it also is a bit messy.
Life was easier when everything was in the ENV.
And not only but also:
So what is unsafe about using an app-factory
The advice given here <http://flask.pocoo.org/docs/patterns/packages>
_
is ::
1. the Flask application object creation has to be in the
__init__.py file. That way each module can import it safely and
the __name__ variable will resolve to the correct package.
2. all the view functions (the ones with a route() decorator on
top) have to be imported in the __init__.py file. Not the object
itself, but the module it is in. Import the view module after
the application object is created.
re: 2., clearly the route decorator expects certain abilities from an instantiated app and cannot function without them. Thats fine.
re: 1., OK we need the name correct. But what is unsafe ? And why? Is it unsafe to import and use the app if it is uninitialised? Well it will break but thats not unsafe. Is it the much vaunted thread-local? Possibly. But if I am plucking app instances willy-nilly from random modules I should expect trouble.
Implications - we do not reference the app object from anything other than the views - essentially we keep our modularisation nice and tight, and pass around dicts, error objects, or even WebObs.
http://flask.pocoo.org/docs/patterns/appdispatch http://flask.pocoo.org/docs/deploying/#deployment http://flask.pocoo.org/docs/patterns/packages/#larger-applications http://flask.pocoo.org/docs/becomingbig