1

I've got a Flask app running under Apache using mod_wsgi. The app needs to do do some initialisation, including setting some top-level variables that need to be accessible inside the request handlers, before it receives any requests. At the moment this initialisation code is just top-level statements in app.py before the request handling methods:

from flask import Flask, Response, request

<other app imports>

APP = Flask(__name__)

# initialisation code

@APP.route(<URL for request #1>)
def request_handler_1():
    # request handler code

@APP.route(<URL for request #2>)
def request_handler_2():
    # request handler code

The application's wsgi file looks like this:

#!/usr/bin/python
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0,"/var/www/myapp")

from myapp.app import APP as application
application.secret_key = <secret key>

I've noticed that the initialisation code is not called until the first request is received. How can I made the initialisation code be executed when the app is loaded by mod_wsgi, before any requests are received?

D. Joe
  • 63
  • 1
  • 10
  • Please show an example of your setup code. – MKesper Feb 24 '17 at 13:17
  • It's just stuff like setting default encoding, defining constants needed by the request handlers inside `app.py` and setting up logging. – D. Joe Feb 24 '17 at 14:06
  • I moved all that initialisation code from the app to the package init, and from the Apache logs I can still see that the app wsgi code first gets executed when the first request is received. There has to be a way surely of having this done when the app is loaded by mod_wsgi. – D. Joe Feb 24 '17 at 14:17

1 Answers1

2

It is happening on first request because by default mod_wsgi will only load your WSGI script file when the first request arrives. That is, it lazily loads your WSGI application.

If you want to force it to load your WSGI application when the process first starts, then you need to tell mod_wsgi to do so.

If you have configuration like:

WSGIDaemonProcess myapp
WSGIProcessGroup myapp
WSGIApplicationGroup %{GLOBAL}
WSGIScriptAlias / /some/path/app.wsgi

change it to:

WSGIDaemonProcess myapp
WSGIScriptAlias / /some/path/app.wsgi process-group=myapp application-group=%{GLOBAL}

It is only when both process group and application group are specified on WSGIScriptAlias, rather than using the separate directives, that mod_wsgi can know up front what process/interpreter context the WSGI application will run in and so preload the WSGI script file.

BTW, if you weren't already using mod_wsgi daemon mode (the WSGIDaemonProcess directive), and forcing the main interpreter context (the WSGIApplicationGroup %{GLOBAL} directive), you should be, as that is the preferred setup.

Graham Dumpleton
  • 57,726
  • 6
  • 119
  • 134
  • I have one further question - I have followed your suggestion about using daemon mode and using the global application group directives. But I would like my Flask app to handle multiple requests using multiple processes or threads. At the moment my app's conf file looks like this: `` `ServerName localhost` `WSGIDaemonProcess myapp` `WSGIScriptAlias / /var/www/myapp/myapp.wsgi process-group=myapp application-group=%{GLOBAL}` `WSGIApplicationGroup %{GLOBAL}` – D. Joe Mar 23 '17 at 11:19
  • Have you looked at the documentation for WSGIDaemonProcess directive? http://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIDaemonProcess.html – Graham Dumpleton Mar 23 '17 at 12:36