Python WSGI Apps on DreamHost Shared Hosting

Continuing in my series on using DreamHost shared hosting as a Python web
development platform, this article will show you how to install a virtualenv in
your local Python directory and enable Passenger to let you serve any Python WSGI
app from DreamHost shared hosting.

If you’re new to this blog, or don’t have a DreamHost account, you might want to
check out previous articles in this series:

Now that you’ve caught up, let’s jump right in!

Setting up a Virtual Environment

The first thing you’ll need to do is grab a tool called virtualenv. This allows
you to set up an Python environment that will be isolated from other Python
environments you might set up in your shared hosting account. This is very
useful when you have several small web apps that each have different package
requirements, since you can install without fear that you’ll clobber some other
web app.

To get your virtual environment up and running, just grab the virtualenv
package from the Python package index and install it:

[sansalvador]$ wget http://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.7.2.tar.gz
...
[sansalvador]$ tar xzf virtualenv-1.7.2.tar.gz 
[sansalvador]$ cd virtualenv-1.7.2
[sansalvador]$ python setup.py install
...
[sansalvador]$ virtualenv --version
1.7.2

Now that you have the virtualenv tool installed into your local Python
installation, creating a virtual environment is quite simple. I like putting my
virtual environments in ~/env:

[sansalvador]$ cd ~
[sansalvador]$ mkdir env
[sansalvador]$ virtualenv env/wsgi-test
New python executable in env/wsgi-test/bin/python
Installing setuptools............done.
Installing pip...............done.

Now to actually use the virtual environment, we need to activate it:

[sansalvador]$ source ~/env/wsgi-test/bin/activate
(wsgi-test)[sansalvador]$ 

And there you go! Now you have a nice full-fledged virtual environment set up
under your home directory. virtualenv has also installed pip in the virtual
environment, so it’s a snap to install other packages.

WSGI Application Serving Using Passenger

For those who aren’t familiar, WSGI is an API standard for serving Python
web applications. We won’t go into detail on the mechanics of it here, except to
say that most (all?) Python web frameworks are compatible with being served as a
WSGI application.

There are a number of different ways to get a Python WSGI application to
run on DreamHost shared accounts, including a CGI-to-WSGI adapter (very slow), a
FastCGI-to-WSGI adapter (somewhat faster, but also somewhat brittle and hard to
debug). The best method I’ve found is to use a little thing called
Passenger that our friends in the Ruby community developed.

What Passenger does is tell DreamHost to send (almost) all the web requests for a
particular domain straight to our WSGI application (in Ruby, it would be a Rack
application). Enabling passenger for a domain is fairly straightforward on
DreamHost. I recommend setting up a subdomain (subdomains are free!) to test it
out.

To enable a subdomain, you need to select “manage domains” on the
DreamHost control panel:

This brings up the domain management screen, where you’ll “Add a New Domain /
Sub-Domain”:

On this page, you’ll have to choose a name for your domain. I recommend taking
the name you already signed up for when you set up your account and making a
subdomain. For instance, if you signed up for mykewlblog.com you’d fill in
passenger-test.mykewlblog.com in the “Domain to Host” field.

There’s a lot of information on this page, so the following diagrams show you
exactly what you need to fill out to move forward:

… scrolling down …

And if everything went well, you should see the following:

(The nice thing, by the way, about adding a subdomain rather than registering a
new domain is that it’s going to be working in minutes rather than hours, as
the message above suggests.)

Now, you wait a few minutes for DreamHost’s magic hamsters to provision the
services, occasionally checking for the presence of your subdomain’s directory in
your shell account (it will be created under your home directory):

(wsgi-test)[sansalvador]$ ls passenger-test.pythonisito.com
ls: cannot access passenger-test.pythonisito.com: No such file or directory

Once it’s running, you’ll need to create a script called passenger_wsgi.py in
the root of your domain (in my case, ~/passenger-test.pythonisito.com). This
script will be called by the Passenger framework to launch your Python app. You
can use the following script, for example, to install a “Hello, world” style app
that verifies you’re running under your virtual environment:

import sys, os

# Switch to the virtualenv if we're not already there
INTERP = os.path.expanduser("~/env/wsgi-test/bin/python")
if sys.executable != INTERP: os.execl(INTERP, INTERP, *sys.argv)

def application(environ, start_response):
    start_response('200 OK', [('Content-type', 'text/plain')])
    return ["Hello, world! from %s: %s\n" % (sys.version, sys.executable)]

Now you’ll also want to create a file tmp/restart.txt under your domain
root. You can modify this file at any time to tell Passenger that you’ve updated
your code and it should restart your application:

(wsgi-test)[sansalvador]$ mkdir passenger-test.pythonisito.com/tmp
(wsgi-test)[sansalvador]$ touch passenger-test.pythonisito.com/tmp/restart.txt

And now we can test that everything works:

(wsgi-test)[sansalvador]$ curl passenger-test.pythonisito.com
Hello, world! from 2.7.3 (default, Jul 10 2012, 18:33:47) 
[GCC 4.3.2]: /home/rick446/env/wsgi-test/bin/python

Hooray! We have just gotten confirmation that the Python we installed in our
virtual environment is being used to serve up requests to our domain. The next
step is installing TurboGears, Flask, Django, Pyramid, or any
other WSGI-compatible Python web framework and writing your app, which will be
covered in future posts.

For now, I’d love to hear if you think this tutorial is useful to you in
getting your WSGI environment bootstrapped on DreamHost shared hosting. Let me
know in the comments below!

7 Responses to Python WSGI Apps on DreamHost Shared Hosting

  1. Pingback: Kevin Rose

    • Pingback: rick446

  2. Pingback: John Gordon

  3. Pingback: Python WSGI web app scripting: a beginners tutorial in a series of blog posts. | Gordon's shares

  4. Pingback: Don

  5. Pingback: Joshua

    • Pingback: rick446