Joe Maller.com

Building Python on Shared Hosting

Why are there so few Google results for “Build Python on Shared Hosting?” Because it’s so ridiculously easy that it took me longer to write this post than it did to download, configure and compile Python 2.7 on two different shared hosting accounts.

These are the steps:

$ mkdir -p ~/opt/python-2.7
$ mkdir ~/src
$ cd ~/src
$ curl -LO http://www.python.org/ftp/python/2.7/Python-2.7.tgz
$ tar -xzvf Python-2.7.tgz
$ cd Python-2.7
$ ./configure --prefix=$HOME/opt/python2.7
$ make
$ make install

Next, create ~/opt/bin if it doesn’t exist already and symlink the new Python binary:

$ mkdir -p ~/opt/bin
$ ln -s ~/opt/python-2.7/bin/python2.7 ~/opt/bin/python

Finally, be sure your $SHELL’s $PATH is configured to look for binaries in ~/opt/bin. I use Bash, so I added the following line to ~/.bashrc:

export PATH=$HOME/opt/bin:$PATH

Ok, so why bother?

I’m lazy. I wanted to save myself a bunch of calls to file.close() by using the more modern with open syntax. Most shared hosts seem to consider Python unimportant, the two I use have Python 2.4.3 installed which is six years old. I couldn’t even import __future__ because __future__ hadn’t been written yet.

Waylan Limberg’s post about installing multiple versions of Python was helpful.

Update: Much has changed in a few years and Python support is finally coming around. A2 Hosting, whose shared servers run cPanel, has a page featuring Python shared hosting. Great to finally see all of this happening.


Django via CGI on shared hosting

Django just isn’t designed to run under CGI.
It won’t run under OS/2, either.*

Well ok, but running Django under CGI is not impossible. It just kind of really sucks. But anyway, to prove it’s possible if not workable, here’s how I got it running on two standard cPanel shared hosts using plain old slow and clunky CGI.

virtualenv

First, install virtualenv. This makes locally managing modules fantastically easy by creating self-contained Python virtual environments. Installing couldn’t be simpler: Get the script, run the script, source your environment.

$ mkdir ~/src && cd ~/src
$ curl -LO http://bitbucket.org/ianb/virtualenv/get/tip.gz
$ tar -xvzf tip.gz
$ python virtualenv/virtualenv.py --distribute ~/python_virtualenv
New python executable in /home/joe/python_virtualenv/bin/python
Installing distribute.............................................
..................................................done.

$ source ~/python_virtualenv/bin/activate 

Now, install Django using pip, which was automatically installed by virtualenv. After sourcing the virtual environment, this works from anywhere.

$ pip install Django
Downloading/unpacking Django
  Downloading Django-1.1.1.tar.gz (5.6Mb): 5.6Mb downloaded
  Running setup.py egg_info for package Django
Installing collected packages: Django
  Running setup.py install for Django
    changing mode of build/scripts-2.4/django-admin.py from 664 to 775
    changing mode of /home/joe/python_virtualenv/bin/django-admin.py to 775
Successfully installed Django

If your host doesn’t block GCC, use pip to be sure your MySQL interface (MySQLdb) is up to date:

$ pip install -U MySQL-python
...
Successfully installed MySQL-python

Django requires MySQLdb version 1.2.1p2 or higher.

Yolk prints a nice, clean list of everything installed in your Python environment, install and run:

$ pip install yolk
$ yolk -l

Django          - 1.1.1        - active 
MySQL-python    - 1.2.3c1      - active 
pip             - 0.6.1        - active 
setuptools      - 0.6c11       - active 
yolk            - 0.4.1        - active 

At this point, I started a new Django project, assigned a database and filled in the necessary values in settings.py. I put the Django project files into the virtual environment to keep everything in the same place. This might not be the best practice, but it makes sense to me.

$ cd ~/python_virtualenv/
$ django-admin.py startproject testproject

The sane part is finished, now onto the kludgery.

Django.cgi

All the CGI shim solutions I found pointed back to a script Paul Sargent uploaded to ticket 2407 back in summer of 2006. It still works: django.cgi

Three lines need editing:

Line 1: Point the CGI’s shebang to the virtualenv Python binary.

#!/home/joe/python_virtualenv/bin/python

Line 95: Add the directory above the Django project directory to Python’s sys.path.

sys.path.append("/home/joe/python_virtualenv")

Line 97: Add the project’s settings to os.environ.

os.environ['DJANGO_SETTINGS_MODULE'] = 'testproject.settings'

htaccess

For Django to respond to URL requests, those urls need to be fed into the django.cgi script. For testing I routed everything from /django to the cgi script by adding the following lines to my top-level htaccess file:

RewriteEngine on
RewriteRule ^cgi-bin/ - [L]
RewriteRule ^django/(.*)$ /cgi-bin/django.cgi/$1 [QSA,L]

The second line isn’t necessary unless pulling Django urls from the webroot, without it, the redirects would loop.

At this point, the Django site should load from /django/… urls.

Finally, as a quick fix for admin media files, I symlinked Django’s admin media directory from my web root:

ln -s ~/python_virtualenv/lib/python2.4/site-packages/django/contrib/admin/media ~/www/media

Conclusion

I spent quite a few hours spread across a couple days researching and figuring out how to get the first install working. The second installation only took about 5 minutes from start until editing Django’s admin pages.

Running Django through CGI is possible, but it is dog slow. There appears to be some caching after the first request, but that first page load often takes an excruciatingly long time.

Further reading, possible improvements

The servers I was working with are both running the almost six year old Python 2.4.3. The wsigref module was introduced with Python 2.5. My goal was to get Django running without compiling anything since some hosts deny access to GCC.

References

These sites were helpful in figuring this out.

The two hosts I tested on were LiquidWeb and A2Hosting. Both have been excellent, dependable hosts. Neither has any Python support to speak of on their shared plans. A2 blocks access to GCC.


How to install Subversion on a shared host

I’ve hosted this site and several others LiquidWeb’s shared servers for probably eight years. They are without question, the most dependable host I’ve ever used. [see update]

But LiquidWeb doesn’t offer Subversion. And I will no longer do web work without it.

For some time I’d been considering leaving LiquidWeb because the lack of svn was now hindering work on my own sites. For the same reason, I’ve had to pass them over several times when clients asked for the best website host recommendations. Then the other night, I stumbled across a discussion about installing Subversion on a shared host. Why didn’t I try that years ago?

(more…)