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 comments on “Python WSGI Apps on DreamHost Shared Hosting

  1. This is an excellent tutorial! Just what I have been looking for.

    But I am unable to import any of my own python files into passenger_wsgi.py, does anyone know why this would be?

    I have put a py file in the same directory are my passenger_wsgi.py file called test.py and this is the code within:


    wibble = 'this string is coming from the test.py'

    And then in my passenger_wsgi.py I have added this line:


    from test import wibble

    And now if I visit my site I just get “An error occurred importing your passenger_wsgi.py” :(

    Also, I assume there is probably an error message being printed somewhere, where can I find it?

    Thanks!
    Kevin

    • Thanks for the comment, Kevin! My best guess as to why you can’t import your own modules is that you haven’t installed them into the virtual environment. If you’ve created a package with a setup.py file, you can typically do this using python setup.py develop. As for the error messages, I’m can’t remember exactly where those are logged. I’d start by looking in your logs/ directory.

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

  3. Is virtualenv a requirement or just something nice to have when you have multiple apps? The reason I ask is I am simply trying to host a single app on DH using python 2.7.6 with passenger. Using the simple application definition in passenger_wsgi.py results in a 500 error. Reverting back to the system installed version of python it works. Running passenget_wsgi.py using my installation from the command line doesn’t result in any errors either (just as a sanity check). Any suggestions on how to track down the issue? Thanks a lot for posting the tutorial.

    • I prefer using virtualenv for everything since it makes it possible to install whichever packages you’re interested in using pip or easy_install. Not sure about your particular issue, but I’d start with finding the passenger logs and seeing why there was a 500 error.

Leave a Reply

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

*

23,320 Spam Comments Blocked so far by Spam Free Wordpress

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>