SJ cartoon avatar

Development Python Web Framework on Dreamhost

It’s never been a secret that I love Python. I think it’s a fantastic programming language which speeds up development by some ridiculous amount. This StackExchange post quotes Guido can Rossum saying that development time is 5-10x greater in Python vs C/C++. This wiki article suggests that it is 6x more ‘expressive’ than C. Whatever the case may be, it’s pretty awesome.

Needing to make a test web server for a demo of our product months and months ago, I decided to look for Python web framework solutions.

The big one, that borderlines on a de facto solution, seems to be Django. It comes built in with a test web server, ORM, and it is backed by lots of Django-specific packages that people have created.

After trying it out for a couple of weeks, I really disliked how bloated it felt. It just felt like I was spending more time in overhead than I was in getting my application up and running. Also, getting the latest version up and running on Dreamhost was a mild nightmare (but that experience helped me immensely with getting other Python web frameworks running on Dreamhost). Even the Django homepage is too busy, bloated, and cluttered for my liking.

I’m not saying there is anything wrong with Django itself, but it just didn’t feel right for me. So, next, I did what comes naturally… Googled!

While there were a slew of alternatives out there, I decided to give Flask a shot. The reason being that it was the opposite of Django. Slim, trim, and didn’t have all the bells and whistles that I would never need. It’s based on the Werkzeug WSGI library, and the Jinja 2 templating library… It doesn’t have a built-in ORM or database, but SQLAlchemy and [database of your choice] are typical extensions to add in.

Preparing Dreamhost for Flask

To get any half-decent Python web framework running on Dreamhost, there are a few housekeeping chores you need to do. Of note, I needed to originally do these changes months ago. Dreamhost is constantly updating, making some of my changes unnecessary, or making this route the less efficient way to do them.

Before I get to any of that, though, I should mention that the first thing to do is to enable Passenger from your Dreamhost CPanel. Without that, the method I’ve suggested below won’t work at all!

To do this, just go to your domain’s CPanel option and enable Passenger and Save.

Dreamhost's Python Passenger support Enabling Passenger from Dreamhost’s CPanel

A newer Python

Personally, I like having the latest stable Python (2.7.6) in use at all times, and right now, Dreamhost is running 2.6.6… I still haven’t switched over to Python 3, because some of the packages I like to use are not fully ported over.

In any case, to start running with a different version of Python, you need to do a manual installation. To make this easier, I’ve made a small script below which should get you started:

# Download Python
cd ~
mkdir tmp

# Download and unarchive Python and VirtualEnv
wget https://python.org/ftp/python/2.7.6/Python-2.7.6.tgz tmp
wget --no-check-certificate https://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.11.2.tar.gz
tar -xzvf tmp/Python-2.7.6.tgz
tar -xzvf tmp/virtualenv-1.11.2.tar.gz

# Install Python, this will take some time
cd Python-2.7.6
./configure
make
make install

# Make and activate a virtual environment for your Flask app
~/Python-2.7.6/bin/python2.7 ~/virtualenv-1.11.2/virtualenv.py ~/domainname/env
source ~/domainname/env/bin/activate
pip install Flask

# Add a sample Flask app
mkdir ~/domainname/DemoApp
touch ~/domainname/DemoApp/DemoFile # Need to fill this with the sample app

# Pull it all together with the passenger_wsgi file
touch ~/domainname/passenger_wsgi.py # Need to fill this with actual passenger_wsgi content

Your first Flask app

Just to get everything started, here is a sample Flask app (taken straight from the Flask homepage):

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()

Your first Passenger file

Finally, the most important part about getting Flask setup on Dreamhost is the passenger_wsgi.py file. It’s a really small file that tells Passenger where to look for your Flask app and what to do with it, when someone navigates to your website:

DH_WORKING_DIR = '/home/username/domainname/'

import sys,os
cwd = os.getcwd()
sys.path.append(cwd)
sys.path.append(os.path.join(DH_WORKING_DIR, 'DemoApp'))

# Make sure the correct Python version is running
if sys.version < '2.7.6':
    os.execl(os.path.join(DH_WORKING_DIR, 'env/bin/python'), 'python2.7.6', *sys.argv)

sys.path.insert(os.path.join(DH_WORKING_DIR, 'env/bin'))
sys.path.insert(os.path.join(DH_WORKING_DIR, 'env/lib/python2.7/site-packages'))

from DemoFile import app as application

The [DH_WORKING_DIR] needs to be modified in your specific situation. There are some ways to make the passenger_wsgi.py file a bit more generic, and use environment variables a bit more wisely to figure some of these things out itself, but I thought it would be nice to be verbose in this file - so everyone can see exactly what I’m doing.

This is largely the same file for Django as well, except there are 2-3 more lines of Django-specific code that need to be written.

Your first error

You’re now ready to navigate to your website’s url to see if everything works. You’ll know it’s all up and running if you see a nice “Hello World” on your webpage.

In reality, the first thing you’ll probably see (and most common thing to see) is: “An error occurred importing your passenger_wsgi.py”

That’s an extremely vague problem, but it definitely points you to the culprit. One test I always run after I’ve written my passenger file is just trying to run the passenger file directly with “python passenger_wsgi.py”

If that succeeds (i.e. no errors pop up), then your passenger file is good to go. For me, because I’m usually typing away pretty quickly and not paying attention, this command will spit back an error directing me to a typo, or invalid path, in my passenger file. Once you fix those, and the python command succeeds, you’ll stop seeing those errors on your webpage.

Before I forget

And before I end this off, I thought I would add in a link to a Dreamhost wiki post about installing Flask. It goes about it in a slightly different way than me (and uses those environment variables I mentioned earlier). For whatever reason, I’m not a fan of installing the Flask app inside of the VirtualEnv directory.

Whichever route you go, all that matters is that you get it up and running!

Feature Photo credit: Jenn and Tony Bot / Foter / CC BY-NC