Warning
This article is out of date.
workingenv has been superceded by virtualenv.
mod_wsgi is an Apache module developed by Graham Dumpleton which makes
dead easy to run WSGI apps under the Apache web-server.
This recipe explains how to run a Pylons app (although it can be easily adapted
to any WSGI app) under mod_wsgi in an isolated workingenv environment in
order to host various apps with different library version requirements.
Note: You don't actually need workingenv.py to run Pylons (or any WSGI app for that matter) under mod_wsgi. workingenv.py just provides a convenient way to create controlled and reproducible environments where libraries can be installed. For a simpler setup that doesn't use workingenv check out this document at the official modwsgi site.
You first need to check out mod_wsgi's source from its SVN repository:
1 | $ svn co http://modwsgi.googlecode.com/svn/trunk modwsgi
|
Provided you have Apache's and Python's headers installed, compilation and
installation is quite straightforward:
1
2
3
4 | $ cd modwsgi
$ ./configure
$ make
$ sudo make install
|
You then need to edit Apache's httpd.conf so it loads mod_wsgi. In Apache 1.3
you'll need to add:
1
2 | LoadModule wsgi_module path_to_modules/mod_wsgi.so
AddModule mod_wsgi.c
|
If you run into any problems or need compiling it for another version of
Apache chechout mod_wsgi's excellent install instructions inside the SVN
checkout.
Here is where mod_wsgi shines as it makes it very easy and straightforward. The
following lines will suffice, although you will probabbly need to configure
other options for a real production site:
1
2
3
4
5
6
7
8
9 | <Directory /Users/alberto/wsgi>
Order allow,deny
Allow from all
</Directory>
NameVirtualHost *:81
<VirtualHost *:81>
WSGIScriptAlias / /Users/alberto/wsgi/myapp.wsgi
</VirtualHost>
|
For the VirtualHost above you should set up apache to listen to port 81 (edit apache's port.conf file).
Refer to the Apache documentation for all available options.
Before even trying to configure your Pylons app and workingenv, first of all
check that mod_wsgi runs properly with a "Hello World" app. Write the following
app into myapp.wsgi.
1
2
3
4
5
6
7
8
9 | def application(environ, start_response):
status = '200 OK'
output = 'Hello World!'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
|
Issue a apachectl restart command and point your web browser to the
VirtualHost you just configured. You should see mod_wsgi and your app greeting
the world cheerfully. If that's not the case, refer to the Troubleshooting
section.
As you have probably noticed, the abobe VirtualHost config refers to a file
called myapp.wsgi. That file should initialize the python sub-interpreter this
script will use (mod_wsgi provides an independent sub-interpreter for each wsgi script by default) and load the WSGI application. Lets see how it looks
like
1
2
3
4
5
6
7
8 | WORKING_ENV = "/Users/alberto/src/python/environments/N50CPanel"
APP_CONFIG = "/Users/alberto/src/python/checkouts/N50CPanel/development.ini"
import activate_workingenv
activate_workingenv.activate_workingenv(WORKING_ENV)
from paste.deploy import loadapp
application = loadapp("config:" + APP_CONFIG)
|
That's all it takes to load a Pylons app from its PasteDeploy config file. The
above code requires some explanation though:
- Uses the activate_workingenv script which you'll need to install somewhere in your PYTHONPATH
- The application is loaded using PasteDeploy's API and bound to the
application variable in which mod_wsgi expect to find the WSGI app by
default.
Environments created with workinenv.py are usually activated using a shell script.
The following script allows activating them from Python (originally found here).
Place it in a file called activate_workingenv.py inside the Python site-packages
directory where it can be found by the user Apache runs as.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | import sys
import os
def activate_workingenv(root):
"""Make modules in a self-contained workingenv available."""
# Find the workingenv Python package root
python_version = '.'.join(map(str, sys.version_info[:2]))
package_root = os.path.join(root, './lib/python' + python_version)
if package_root not in sys.path:
# Find and insert setuptools into sys.path, only if it hasn't done
# before (if the script has been reloaded)
sys.path.insert(0, package_root)
real_setuptools = open(os.path.join(package_root,
'setuptools.pth')).read().strip()
sys.path.insert(0, os.path.join(package_root, real_setuptools))
# Load all distributions into the working set.
from pkg_resources import working_set, Environment
env = Environment(root)
env.scan()
distributions, errors = working_set.find_plugins(env)
for dist in distributions:
working_set.add(dist)
|
(Note: This version will not change os.environ['PATH'] nor os.environ['LD_LIBRARY_PATH'] as those are global to the whole Apache process and we don't want or need them changing every time a workingenv is activated)
If you don't have permissions or, for any other reason, you cannot install it at the site-packages directory, alternatively you could modify sys.path inside your .wsgi script like this:
1
2
3
4 | import sys
sys.path.append("/directory/where/activate_workingenv.py/lives")
import activate_workingenv
....
|
You should now be able to issue an apachectl restart command and access your
Pylons app at the VirtualHost you just configured. Keep in mind though:
- Your data dir should be writable by the user Apache runs as.
- EvalException should be disabled if running in a multi-process Apache MPM
If anything goes wrong, first check your apache error.log, double-check the
files you created and refer to mod_wsgi's documentation.
mod_wsgi and workingenv are a great combination when used together to host
multiple apps in an Apache process:
- mod_wsgi is dead easy to configure, lightweight and the fastest apache-wsgi
gateway yet. It's still in dev though.
- workingenv creates nicely isolated environments where you can install
different versions of the same eggs side by side in the same machine.
Together they allow to host several independent WSGI apps, along their
different requirements in the same Apache process.
Hmmm, I'm beginning to smell Python commodity hosting... :)
EvalException could be disabled (safely?) by appending the line
to your development.ini configuration file. Almost no documentation around.