Robin's Blog

How to: Fix Flask WSGI webapp hanging when importing a module (such as numpy or matplotlib)

I’ve spent a long time over the last few days struggling with a problem with a Flask webapp that I’ve been developing. The app worked fine on my local computer, but when I tried to deploy it to my web server and run it via WSGI it seemed to ‘just hang’.

That is – when I visited the URL my browser said Waiting…, but there was nothing in the Apache error log or access log, it didn’t seem to have even registered that I was trying to visit the page. I had no idea what was going on, and after a long period of debugging, I found that removing some of the module imports stopped it hanging. In this case, it was removing the import for Py6S (my Python interface to the 6S Radiative Transfer Model) and matplotlib.

I had no idea why this fixed the problem, and after a lot of searching I found that it was all caused by my Apache WSGI configuration. Documenting this here will hopefully help others with the problem – and also remind me what to do next time that I want to deploy a WSGI app.

Basically, if you’ve got a directory structure like this:

/usr/local/www/wsgi-scripts
├── Web6S
├── static
│   ├── custom.css
├── templates
│   └── index.html
├── web6s.py
└── web6s.wsgi

That is, a folder for the app (Web6S in this example), with the main file for the app given the same name (web6s.py), and a similarly-named WSGI file (web6s.wsgi).

The WSGI file has the following contents:

import sys
sys.path.insert(0, '/usr/local/www/wsgi-scripts/Web6S')
from web6s import app as application

which alters the Python path to add the directory that the app is in, and then imports the app object, calling it application (which is what WSGI requires).

That’s fairly simple – the harder bit is the Apache configuration. I’d suggest creating a virtualhost for this, to keep the configuration separate from your other bits of Apache configuration. My configuration is:

### WSGI for Web6S app
WSGIDaemonProcess flaskapp threads=5
WSGIScriptAlias /web6s /usr/local/www/wsgi-scripts/Web6S/web6s.wsgi process-group=flaskapp application-group=%{GLOBAL}
<Directory /usr/local/www/wsgi-scripts/Web6S>
    AllowOverride None
	Require all granted
</Directory>

Probably these bits aren’t all essential, but this is what seems to work for me. I didn’t have bits like the WSGIDaemonProcess line before, but adding them fixed it (I can’t guarantee that this is correct, but it works for me).

So, adding those lines into the correct files and restarting Apache should make it work – Good Luck!


Categorised as: How To, Python


One Comment

  1. The specific solution is forcing use of the main interpreter by setting the application group to %{GLOBAL}. It is documented in http://code.google.com/p/modwsgi/wiki/ApplicationIssues#Python_Simplified_GIL_State_API

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>