<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>WombatNation &#187; Python</title>
	<atom:link href="http://www.wombatnation.com/category/python/feed" rel="self" type="application/rss+xml" />
	<link>http://www.wombatnation.com</link>
	<description>Speech Applications, MySQL, Python, Soccer, Java, Beer and Incinerating Toilets</description>
	<lastBuildDate>Mon, 30 Jan 2012 08:10:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Tweeting by Phone with PhoneBlogger</title>
		<link>http://www.wombatnation.com/2011/03/tweeting-by-phone-with-phoneblogger</link>
		<comments>http://www.wombatnation.com/2011/03/tweeting-by-phone-with-phoneblogger#comments</comments>
		<pubDate>Sun, 20 Mar 2011 23:06:52 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[PhoneBlogger]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[VoiceXML]]></category>

		<guid isPermaLink="false">http://www.wombatnation.com/?p=905</guid>
		<description><![CDATA[In late 2002, I thought it would be cool to build an application that allowed you to blog by phone. Tools, libraries and hosted services were a bit more limited back then, but after a few months of learning, coding and debugging, I managed to release the first version of PhoneBlogger in January 2003. Along [...]]]></description>
			<content:encoded><![CDATA[<p>In late 2002, I thought it would be cool to build an application that allowed you to blog by phone. Tools, libraries and hosted services were a bit more limited back then, but after a few months of learning, coding and debugging, I managed to release the first version of <a href="http://www.wombatnation.com/phoneblogger/">PhoneBlogger</a> in January 2003. Along the way, I learned a lot about <a href="http://python.org">Python</a>, <a href="http://voicexml.org">VoiceXML</a>, JavaScript, XML-RPC, audio encoding, shared web hosting and command line tools for Linux.</p>

<p>Fast forward nearly ten years and not only have the tools and libraries come a long way, but there are many more free or inexpensive hosted services that simplify building a tool/service like PhoneBlogger. Instead of hosting the application code on a shared hosting site, I can now build and deploy on <a href="http://code.google.com/appengine/">Google App Engine</a>. Though scalability is not an issue for my personal use of PhoneBlogger, if it were turned into a public service, App Engine would make scaling much simpler and more economical. App Engine also makes deployment a snap, though with a small amount of work, so would <a href="http://fabfile.org/">Fabric</a>. For my PhoneBlogger rewrite, I decided to use App Engine.</p>

<p>In the original version of PhoneBlogger, I coded a bunch of static VoiceXML and JavaScript for managing the telephone interaction with a caller. At the time, three of the most prominent services for VoiceXML developers were <a href="http://studio.tellme.com">Tellme</a> (now owned by Microsoft), <a href="http://cafe.bevocal.com">BeVocal</a> (now owned by Nuance) and <a href="http://evolution.voxeo.com">Voxeo</a> (still independent). I had to write slightly different code for Tellme and BeVocal, but the differences weren&#8217;t that significant. I think it would have been pretty simple to port to Voxeo, as well. Improved support of VoiceXML 2 would now likely allow me to use the same code on each platform.</p>

<p>While VoiceXML is still a great option for building speech apps, a couple of new services bring you simple APIs for building speech or DTMF (touchtone) applications, at the cost of portability. This time around I&#8217;ve started with <a href="http://twilio.com">Twilio</a>. I very quickly turned a Python/GAE example from the Twilio website into a DTMF app for tweeting by phone. Although speech recognition allows you to build much more complex and natural applications, many simple applications can be built quickly and easily with just support for pressing keys to provide input. PhoneBlogger falls into that category, for now.</p>

<p>One very convenient thing about Twilio is that I can use their platform to capture and host recordings in a format that is simple to play back in a web browser. If I were really concerned about longevity of the recordings I could easily retrieve them and store them elsewhere, but I&#8217;m okay with keeping them on Twilio servers for now. That&#8217;s an easy enhancement to add later. The biggest downside for tweeting the Twilio links is that the Twilio recording URLs are ginormous. Fortunately, the goo.gl URL shortener made quick work of that problem.</p>

<p>I&#8217;m also going to take a look at porting my code to <a href="http://tropo.com">Tropo</a>, which is a service offered by Voxeo. Tropo is built on Voxeo&#8217;s Prophecy platform and offers speech recognition as an option.</p>

<p>I decided to begin the rewrite by first supporting tweeting by phone. Twitter offers a great API, which is made even simpler by libraries like Tweepy. I highly recommend first checking out the OAuth support in any library for Twitter you might consider using. OAuth can be a complex beast, but libraries like <a href="http://joshthecoder.github.com/tweepy/">Tweepy</a> make it almost trivial.</p>

<p>The original PhoneBlogger source code and a couple iterations of it are <a href="http://sourceforge.net/projects/phoneblogger/">available on SourceForge</a>. I wasn&#8217;t particularly interested in learning about CVS at the time, so I just uploaded tarballs of all the code. While SourceForge has improved a lot, I&#8217;ve become more of a fan of GitHub. Google Code, LaunchPad and BitBucket are also great options. I started using LaunchPad when working on a <a href="https://launchpad.net/gearmanij">Java library for Gearman</a>, but then set up a <a href="https://github.com/RobertStewart">couple of repos on GitHub</a> when I started working on <a href="https://github.com/log4mongo/log4mongo-java">Log4mongo-Java</a>. I&#8217;m much happier with Git, Bazaar and Mercurial than Subversion and CVS (Caveman Versioning System). I&#8217;ve already started posting code for the new <a href="https://github.com/RobertStewart/phoneblogger">phoneblogger project on GitHub</a>.</p>

<p>As of now, the new version of PhoneBlogger supports tweeting by phone. All the code is on GitHub, along with a README file with the basic steps to set it up for yourself. In an upcoming blog post I&#8217;ll walk through those steps in a little more detail.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.wombatnation.com/2011/03/tweeting-by-phone-with-phoneblogger/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Speaking at Mongo SV 2010</title>
		<link>http://www.wombatnation.com/2010/11/speaking-at-mongo-sv-2010</link>
		<comments>http://www.wombatnation.com/2010/11/speaking-at-mongo-sv-2010#comments</comments>
		<pubDate>Wed, 17 Nov 2010 23:26:19 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Conference]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.wombatnation.com/?p=870</guid>
		<description><![CDATA[I&#8217;ve very excited to be speaking on Logging Application Behavior to MongoDB at Mongo SV 2010 in Mountain View on December 3rd. Interest in the conference has soared and 10Gen is now expecting 500 attendees. Just a week ago, they were at 300 attendees. They had to add a fourth track of talks to handle [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/images/mongoSV-badge-blue.png" alt="Mongo SV 2010 badge" /></p>

<p>I&#8217;ve very excited to be speaking on <strong>Logging Application Behavior to <a href="http://www.mongodb.org/">MongoDB</a></strong> at <a href="http://www.10gen.com/conferences/mongosv2010">Mongo SV 2010 in Mountain View</a> on December 3rd. Interest in the conference has soared and <a href="http://www.10gen.com/">10Gen</a> is now expecting 500 attendees. Just a week ago, they were at 300 attendees. They had to add a fourth track of talks to handle the interest.</p>

<p>If you&#8217;re going to be at Mongo SV, please let me know or look for me at the conference. I&#8217;ll obviously be easy to find between 2:45 and 3:30 pm.</p>

<p>In my talk I&#8217;m planning to cover:</p>

<ul>
    <li>Why MongoDB is useful for application logging</li>
    <li>Strategies for logging to MongoDB</li>
    <li>Commonalities in logging libraries</li>
    <li>General purpose and MongoDB-specific logging libraries for:
<ul>
    <li>Java</li>
    <li>Python</li>
    <li>Ruby</li>
    <li>PHP</li>
    <li>C#/.NET</li>
</ul>
</li>
    <li>Analyzing logs in MongoDB</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.wombatnation.com/2010/11/speaking-at-mongo-sv-2010/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django on DreamHost VPS</title>
		<link>http://www.wombatnation.com/2010/06/django-on-dreamhost-ps</link>
		<comments>http://www.wombatnation.com/2010/06/django-on-dreamhost-ps#comments</comments>
		<pubDate>Wed, 02 Jun 2010 07:58:00 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[DreamHost]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://www.wombatnation.com/?p=821</guid>
		<description><![CDATA[I recently successfully migrated my first Django app from DreamHost shared hosting to a DreamHost VPS (virtual private server). I hope this info will be useful to others. The following two blog posts were absolutely key to me getting this working, especially the first one. Thanks Preston and Graham! Setting up Pinax on DreamHost Private Server [...]]]></description>
			<content:encoded><![CDATA[<p>I recently successfully migrated my first Django app from <a href="http://dreamhost.com/">DreamHost</a> shared hosting to a DreamHost VPS (virtual private server). I hope this info will be useful to others. The following two blog posts were absolutely key to me getting this working, especially the first one. Thanks Preston and Graham!</p>

<ul>
    <li><a href="http://ptone.com/dablog/2009/10/setting-up-pinax-on-dreamhost-private-server/">Setting up Pinax on DreamHost Private Server</a></li>
    <li><a href="http://blog.dscpl.com.au/2010/03/improved-wsgi-script-for-use-with.html">An Improved WSGI Script for use with Django</a></li>
</ul>

<h2>Disable Passenger if Migrating from Shared Hosting</h2>

<p>If you set up your shared site for Django recently, you likely enabled <a href="http://wiki.dreamhost.com/Passenger_WSGI">Phusion Passenger to serve your Django projects</a>. While it works great on shared hosting, you&#8217;re better off using the more conventional <a href="http://code.google.com/p/modwsgi/">mod_wsgi</a> approach on a PS. If you don&#8217;t disable it, it will interfere with mod_wsgi AND use up a lot of the memory you are paying for on your PS. In the graph below, memory use had been steady at about 250 MB. After disabling Passenger, memory use leveled off at around 50 MB. This chart is from the DreamHost control panel.</p>

<p><a href="http://wombatnation.com/w/wp-content/uploads/2010/06/mem_post_passenger.gif"><img class="size-full wp-image-834" title="Memory Use Post-Passenger" src="http://wombatnation.com/w/wp-content/uploads/2010/06/mem_post_passenger.gif" alt="" width="627" height="292" /></a></p>

<h2>Disable DreamHost Management of Web Server</h2>

<p>To enable mod_wsgi and make a few directories accessible by Apache, you will need to modify httpd.conf. The DreamHost control panel does a great job of managing httpd.conf for you. But, unless you want to be constantly merging in your changes, you need to manage httpd.conf yourself.</p>

<p>Under Private Servers, select Configure Server. Then in the Web Server Configuration section, uncheck DreamHost Managed and click the Save psNNNNN settings&#8230; button.</p>

<p>To edit the config and restart Apache, you need to setup a user with sudo privileges. I created a special user account solely for this purpose. After creating the new user account through the control panel, give that user sudo privileges via the Manage Admin Servers entry in the Private Servers section of the DreamHost control panel.</p>

<h2>Important Directories</h2>

<p>In addition to knowing about /usr/local/dh/apache2, there are a couple of other important directories, some of which need to be added. Replace YOU with your username. This directory layout isn&#8217;t required, but you&#8217;ll have to adjust the rest of the instructions if you save things elsewhere.</p>

<ul>
    <li>/home/YOU/src &#8211; Convenient place for downloading libraries for building and installing</li>
    <li>/home/YOU/wsgi-scripts &#8211; Will contain a wsgi-script for each Django project</li>
    <li>/home/YOU/projects &#8211; Will contain all Django projects</li>
</ul>

<p>Since Apache will be accessing these directories as a different user, make sure the directories are accessible (i.e., chmod 755). I got bit by this as part of my shared hosting migration. On shared hosting, scripts get run under your user, so my project didn&#8217;t need to be group or other executable.</p>

<p>Inside of a Django project, I use the following layout. In this example, I&#8217;m serving up static files with the same web server. In the instructions below, I&#8217;ll be setting up an alias to the media directory from Apache.
<pre><code>__init.py__
manage.py
settings.py
templates
  |---- app1
     |---- base.html
     |---- index.html
     |---- ...
  |---- app2
     ...
media
  |---- css
  |---- js
  ...
...</code></pre>
To keep people from accessing directory listings of your media directory, you can add a .htaccess file to that directory with the following contents.
<pre><code>Options -Indexes</code></pre></p>

<h2>Setup Python</h2>

<p>I ran into issues with Python 2.6 (No <em>module</em> named <em>_md5</em>), so I recommend sticking with Python 2.5. In case the default Python version on your server is 2.4, make 2.5 the default:
<pre><code>$ sudo rm /usr/bin/python
$ sudo ln -s /usr/bin/python2.5 /usr/bin/python</code></pre>
Create a directory in which to download and install libraries.
<pre><code>$ mkdir ~/src
$ cd ~/src</code></pre>
Download and install setuptools for Python 2.5.
<pre><code>wget http://pypi.python.org/packages/2.5/s/setuptools/setuptools-0.6c11-py2.5.egg#md5=64c94f3bf7a72a13ec83e0b24f2749b2
sudo sh setuptools-0.6c11-py2.5.egg</code></pre>
Upgrade Django, if desired.
<pre><code>$ sudo easy_install pip
$ pip install -U django</code></pre>
Download and build MySQLdb library. I prefer oursql, but it is easier to get started with MySQLdb.
<pre><code>$ tar xzf MySQL-python-1.2.3c1.tar.gz
$ cd MySQL-python-1.2.3c1
$ sudo python setup.py install</code></pre>
Preston&#8217;s instructions also cover the Python Imaging Library and virtualenv. I&#8217;ve skipped them here to keep the instructions shorter. You can easily install them later.</p>

<p>Before preceding with mod_wsgi, make sure your Django app runs on the Django dev server. It&#8217;s a lot easier to sort out issues with settings.py at this stage.</p>

<p>Create your Django project with django-admin.py or copy an existing project into the projects directory mentioned above.
In settings.py, add a variable that determines the location of your project directory. You&#8217;ll also need to add <code>import os</code> at the top of the file.
<pre><code>PROJECT_ROOT = os.path.realpath(os.path.dirname(<strong>file</strong>))</code></pre>
And then set up your media and templates:
<pre><code>MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'media')
TEMPLATE_DIRS = (os.path.join(PROJECT_ROOT, 'templates'),)</code></pre>
In the instructions below, I set up aliases for Apache to the project media and admin media directoris, so I set both media URLs to /media/.
<pre><code>MEDIA_URL = '/media/'
ADMIN_MEDIA_PREFIX = '/media/'</code></pre></p>

<h2>Running with the Devserver</h2>

<p>From your project directory, create the database if your app needs one (this assumes you&#8217;ve already set up a MySQL database through the control panel or manually).
<pre><code>$ chmod u+x manage.py
$ ./manage.py syncdb</code></pre>
Start the dev server and make sure your app loads.
<pre><code>./manage.py runserver 0.0.0.0:8000</code></pre>
If not, check the output that is being logged to the console. You may also want to temporarily change settings.py so that <code>DEBUG = True</code>. Kill the dev server with ctrl-c once you&#8217;ve got things sorted out.</p>

<h2>Install mod_wsgi</h2>

<p>Download, build and install mod_wsgi.
<pre><code>$ cd ~/src
$ wget http://modwsgi.googlecode.com/files/mod_wsgi-3.0c5.tar.gz
$ tar xzf mod_wsgi-3.0c5.tar.gz
$ cd mod_wsgi-3.0c5
$ ./configure --with-apxs=/usr/local/dh/apache2/template/sbin/apxs --with-python=/usr/bin/python
$ make
$ sudo make install</code></pre></p>

<h2>Create a WSGI Script</h2>

<p>In the /home/YOU/wsgi-scripts directory create a PROJECT.wsgi file, where you replace PROJECT with your project&#8217;s name. Below are the contents of mine. Replace YOU and PROJECT with appropriate values. See the comments for this post for an explanation of why you should use /var/tmp instead of /tmp for PYTHON_EGG_CACHE.</p>


<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># setup_tools will try to cache egg files in surprising locations where the</span>
<span style="color: #808080; font-style: italic;"># apache user likely doesn't have write access unless you do this</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'PYTHON_EGG_CACHE'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'/var/tmp'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Ensure that parent directory of project is on PYTHONPATH</span>
<span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>.<span style="color: black;">insert</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #483d8b;">'/home/YOU/projects'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'DJANGO_SETTINGS_MODULE'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'PROJECT.settings'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>
application = django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>.<span style="color: black;">WSGIHandler</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> test_wsgi<span style="color: black;">&#40;</span>environ, start_response<span style="color: black;">&#41;</span>:
    status = <span style="color: #483d8b;">'200 OK'</span>
    output = <span style="color: #483d8b;">'Hello World! wsgi py <span style="color: #000099; font-weight: bold;">\n</span>'</span> + <span style="color: #dc143c;">sys</span>.<span style="color: black;">version</span> + <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span> + <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span><span style="color: black;">&#41;</span>
    response_headers = <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Content-type'</span>, <span style="color: #483d8b;">'text/plain'</span><span style="color: black;">&#41;</span>,
                        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Content-Length'</span>, <span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>output<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
    start_response<span style="color: black;">&#40;</span>status, response_headers<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span>output<span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Uncomment next line to test that basic mod_wsgi setup works</span>
<span style="color: #808080; font-style: italic;"># and to see the contents of PYTHONPATH</span>
application = test_wsgi</pre></div></div>


<p>Note, that the last line is uncommented. That will allow us to first make sure that mod_wsgi is working, in general. Later, we&#8217;ll comment it out.</p>

<h2>Test mod_wsgi</h2>

<p>Next you need to edit the Apache config file. Change psNNNNN to your actual private server ID in each of the following steps.</p>

<p>To keep some of the following commands short, cd into the apache2 directory:
<pre><code>$ cd /usr/local/dh/apache2</code></pre>
To edit the Apache config (of course, you can use another editor besides vi):
<pre><code>$ sudo vi apache2-psNNNNN/etc/httpd.conf</code></pre>
To restart Apache:
<pre><code>$ sudo /etc/init.d/httpd2 restart apache2-psNNNNN</code></pre>
To view the Apache error log:
<pre><code>$ sudo less apache2-psNNNNN/logs/error.log</code></pre>
Open httpd.conf in an editor, search for the modules section and add the following line:
<pre><code>LoadModule wsgi_module /dh/apache2/template/lib/modules/mod_wsgi.so
</code></pre>
Then, search for the VirtualHost section for your domain. At the end before , add the following while replacing YOU and PROJECT as appropriate:
<pre><code># wsgi
&lt;Directory /home/YOU/wsgi-scripts&gt;
Order allow,deny
Allow from all
&lt;/Directory&gt;</code></pre></p>

<h1>absolute path</h1>

<p>WSGIScriptAlias / /home/YOU/wsgi-scripts/PROJECT.wsgi</p>

<p>&lt;Directory "/home/YOU/projects/PROJECT/media"&gt;
Allow from all
Order allow,deny
&lt;/Directory&gt;</p>

<p>&lt;Directory "/usr/lib/python2.5/site-packages/django/contrib/admin/media"&gt;
Allow from all
Order allow,deny
&lt;/Directory&gt;</p>

<p>Alias "/media/" "/home/YOU/projects/PROJECT/media/"</p>

<h1>note some use hyphen - others _</h1>

<p>Alias "/media/" "/usr/lib/python2.5/site-packages/django/contrib/admin/media/"

Only the first two sections are needed for a basic mod_wsgi test. If you run into any problems, try it with just the part up to and including the WSGIScriptAlias.</p>

<p>Restart Apache and access what would be the normal URL for your Django app. You should see something like:
<pre><code>
Hello World! wsgi py
2.5 (release25-maint, Jan 24 2010, 14:37:54)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)]
/home/YOU/projects
/usr/lib/python2.5/site-packages/setuptools-0.6c11-py2.5.egg
/usr/lib/python2.5/site-packages/MySQL_python-1.2.3c1-py2.5-linux-x86_64.egg
/usr/lib/python2.5/site-packages/pip-0.7.1-py2.5.egg
/usr/lib/python25.zip
/usr/lib/python2.5
/usr/lib/python2.5/plat-linux2
/usr/lib/python2.5/lib-tk
/usr/lib/python2.5/lib-dynload
/usr/local/lib/python2.5/site-packages
/usr/lib/python2.5/site-packages
/usr/lib/python2.5/site-packages/PIL
/usr/lib/site-python
</code></pre></p>

<h2>Test Django with mod_wsgi</h2>

<p>Once that&#8217;s working, comment out the last line in your WSGI script and hopefully your app will load.</p>

<h2>Troubleshooting</h2>

<p>I found it helpful to open a couple of console windows where I could:</p>

<ul>
    <li>Log in as admin user and tail the Apache error log (sudo tail -f apache2-psNNNNN/logs/error.log)</li>
    <li>Log in as admin user and restart Apache as necessary</li>
    <li>Log in as regular user and tail the HTTP error log (tail -f /home/YOU/DOMAIN/http/error.log)</li>
    <li>Log in as regular user and edit my wsgi script, settings.py, etc.</li>
</ul>

<p>The output in the error logs was key to solving most of the problems I ran into. The two web pages I mentioned at the beginning of this post were also crucial. Graham&#8217;s post includes a lot of useful detail on WSGI. Reading it enabled me to better understand what the error messages I was seeing really meant.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.wombatnation.com/2010/06/django-on-dreamhost-ps/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Lifehacker Poll Says DreamHost Best Personal Web Host</title>
		<link>http://www.wombatnation.com/2010/05/lifehacker-poll-says-dreamhost-best-personal-web-host</link>
		<comments>http://www.wombatnation.com/2010/05/lifehacker-poll-says-dreamhost-best-personal-web-host#comments</comments>
		<pubDate>Wed, 26 May 2010 02:52:43 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[DreamHost]]></category>
		<category><![CDATA[Google App Engine]]></category>

		<guid isPermaLink="false">http://www.wombatnation.com/?p=828</guid>
		<description><![CDATA[DreamHost ended up at the top of a Lifehacker poll today for best personal web host. Well, not counting &#8220;Other&#8221;. Given how many web hosts there are and the likelihood that most of the people voting have experience with only one web host, it&#8217;s not surprising that Other came out on top. Still, DreamHost got almost [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://dreamhost.com/">DreamHost</a> ended up at the top of a <a href="http://lifehacker.com/5546722/best-personal-web-host-dreamhost">Lifehacker poll today for best personal web host</a>. Well, not counting &#8220;Other&#8221;. Given how many web hosts there are and the likelihood that most of the people voting have experience with only one web host, it&#8217;s not surprising that Other came out on top. Still, DreamHost got almost 26% of the vote, more than double their closest competitor.</p>

<p>I&#8217;ve hosted this site on DreamHost since 2002 and have been very happy with their performance, attitude and sense of humor. I&#8217;ve added two more domains since then.</p>

<p>A few months ago I developed and deployed a simple Django app for <a href="http://soccer.wombatnation.com/magicnumbers/">calculating magic numbers for soccer leagues</a> on shared hosting. The app scrapes league standings off websites and displays a matrix of teams and the magic numbers. DreamHost did a fantastic job of making it really easy to <a href="http://wiki.dreamhost.com/Passenger_WSGI">deploy a Django app on shared hosting with Phusion Passenge</a>r. I only had to make a few config changes from running it locally on the Django development server.</p>

<p>Recently I moved onto a Private Server and ported my app to run on mod_wsgi. Although mod_wsgi is the preferred way (I think) of deploying Django apps, it required a lot more debugging and config work on my part. I&#8217;m working on a blog post to cover everything I had to do to get it working. Part of the problem came from me having previously had it running on shared hosting. Someone starting with a private server would have had fewer issues.</p>

<p>I&#8217;m also planning to port the app to run on Google App Engine. Since there is no database backend, it should be very straightforward.</p>

<p>This is all leading up to a much more complicated web app that I plan to run on my DreamHost PS, as well as GAE. The data it will be storing is a natural fit for a relational database, so it will be interesting getting the app working on the App Engine datastore. I&#8217;m also going to try MongoDB as the datastore.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.wombatnation.com/2010/05/lifehacker-poll-says-dreamhost-best-personal-web-host/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django Bash Shell Completion</title>
		<link>http://www.wombatnation.com/2010/01/django-bash-shell-completion</link>
		<comments>http://www.wombatnation.com/2010/01/django-bash-shell-completion#comments</comments>
		<pubDate>Mon, 11 Jan 2010 07:43:22 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.wombatnation.com/?p=766</guid>
		<description><![CDATA[Django includes a Bash shell completion script, which can save a lot of time. The tutorial recommends installing it, but doesn&#8217;t explain how. Fortunately, its the same as for any other Bash shell completion script. Here&#8217;s how I did it for Django. Add an environment variable for the location where you installed Django. For example, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.djangoproject.com/">Django</a> includes a Bash shell completion script, which can save a lot of time. The tutorial recommends installing it, but doesn&#8217;t explain how. Fortunately, its the same as for any other Bash shell completion script. Here&#8217;s how I did it for Django.</p>

<ul>
    <li>Add an environment variable for the location where you installed Django. For example, add the following line to ~/.bash_profile:
<code>export DJANGO_HOME=/Users/rstewart/code/Django-1.1.1</code></li>
    <li>Add a line after this one in ~/.bash_profile to read the script, e.g.,
<code>source $DJANGO_HOME/extras/django_bash_completion</code></li>
    <li>After saving .bash_profile, open a new terminal or run <code>source ~/.bash_profile</code></li>
</ul>

<p>Now, you can press tab to complete commands. Below, I pressed tab after entering &#8220;manage.py&#8221;.</p>

<p><pre><code>$ python manage.py
compilemessages   diffsettings      loaddata          runserver         sqlclear          sqlreset          syncdb
createcachetable  dumpdata          makemessages      shell             sqlcustom         sqlsequencereset  test
createsuperuser   flush             reset             sql               sqlflush          startapp          validate
dbshell           inspectdb         runfcgi           sqlall            sqlindexes        startproject
</code></pre></p>
]]></content:encoded>
			<wfw:commentRss>http://www.wombatnation.com/2010/01/django-bash-shell-completion/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL, Python and Snow Leopard</title>
		<link>http://www.wombatnation.com/2009/12/mysql-python-and-snow-leopard</link>
		<comments>http://www.wombatnation.com/2009/12/mysql-python-and-snow-leopard#comments</comments>
		<pubDate>Wed, 30 Dec 2009 01:17:30 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.wombatnation.com/?p=763</guid>
		<description><![CDATA[I just updated an old post on using Python with MySQL on OS X. The good news is that you don&#8217;t need to create an extra directory of symbolic links anymore. The not really bad news is that you have to be careful about 32-bit versus 64-bit. Ideally, you&#8217;ll first upgrade to a 64-bit version [...]]]></description>
			<content:encoded><![CDATA[<p>I just updated an old post on using <a href="http://www.wombatnation.com/2008/02/mysql-support-from-python-on-os-x">Python with MySQL on OS X</a>. The good news is that you don&#8217;t need to create an extra directory of symbolic links anymore. The not really bad news is that you have to be careful about 32-bit versus 64-bit.</p>

<p>Ideally, you&#8217;ll first upgrade to a 64-bit version of MySQL 5.1 or later, unless you already have. Then, follow Geert&#8217;s simple <a href="http://geert.vanderkelen.org/2009/09/mysql-python-and-macos-x-106-snow.html">instructions for building the MySQL Python connector</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.wombatnation.com/2009/12/mysql-python-and-snow-leopard/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Population after Katrina</title>
		<link>http://www.wombatnation.com/2008/07/population-after-katrina</link>
		<comments>http://www.wombatnation.com/2008/07/population-after-katrina#comments</comments>
		<pubDate>Wed, 23 Jul 2008 03:37:44 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Hurricane Katrina]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.wombatnation.com/?p=564</guid>
		<description><![CDATA[While analyzing a bunch of US Census data at work to build out an even more comprehensive geographical database for Voxify&#8217;s speech apps, I ran into an unexpected error. I wrote a Python script to parse a CSV file that contains population data from 2000 and estimates for 2001-2007. The code extracted the data I [...]]]></description>
			<content:encoded><![CDATA[<p>While analyzing a bunch of <a href="http://www.census.gov/popest/cities/files/SUB-EST2007-all.csv">US Census data</a> at work to build out an even more comprehensive geographical database for Voxify&#8217;s speech apps, I ran into an unexpected error. I wrote a Python script to parse a CSV file that contains population data from 2000 and estimates for 2001-2007. The code extracted the data I was interested in, cleaned it up to remove extraneous data and inserted it into a MySQL database. But, my program got an error when it was inserting the population data for Bay St. Louis, Mississippi.</p>

<p>Apparently, the US Census team was so uncertain of the post Katrina population in Bay St. Louis  they used a &#8220;Z&#8221; in place of a number for 2006 and 2007. They did the same for Pass Christian, Long Beach and Waveland. So then I decided to look at their estimates for nearby cities.</p>

<table border="1">
<tr>
<th>City</th><th>2005</th><th>2006</th><th>2007</th>
</tr>
<tr>
<td>Biloxi</td><td>50,614</td><td>44,624</td><td>44,292</td>
</tr>
<tr>
<td>Gulfport</td><td>73,340</td><td>65,296</td><td>66,271</td>
</tr>
<tr>
<td>D&#8217;Iberville</td><td>8267</td><td>7285</td><td>7423</td>
</tr>
<tr>
<td>Ocean Springs</td><td>17,573</td><td>16,813</td><td>17,246</td>
</tr>
<tr>
<td>New Orleans</td><td>453,726</td><td>210,198</td><td>239,124</td>
</tr>
</table>

<p>The population decrease in New Orleans has been written about quite a bit, but it is still startling to see the numbers next to each other. I don&#8217;t remember seeing population data for the Mississippi coastal cities.</p>

<p>I had been looking for an excuse to play around with the Google Charts API. Here&#8217;s a graph of the population decreases for some of the cities.</p>

<p><img src="http://chart.apis.google.com/chart?cht=lc&#038;chd=t:73.340,65.296,66.271|50.614,44.624,44.292|17.573,16.813,17.246&#038;chds=15,75&#038;chs=250x200&#038;chdl=Gulfport|Biloxi|Ocean%20Springs&#038;chco=ff0000,00ff00,0000ff&#038;chxt=x,y&#038;chxl=0:|2005|2006|2007|1:|15,000|75,000" alt="Population decrease for Gulfport, Biloxi, and Ocean Springs" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.wombatnation.com/2008/07/population-after-katrina/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL Support from Python on OS X</title>
		<link>http://www.wombatnation.com/2008/02/mysql-support-from-python-on-os-x</link>
		<comments>http://www.wombatnation.com/2008/02/mysql-support-from-python-on-os-x#comments</comments>
		<pubDate>Tue, 19 Feb 2008 07:23:00 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.wombatnation.com/2008/02/mysql-support-from-python-on-os-x</guid>
		<description><![CDATA[It was more work than it should have been, but you can get access to a MySQL database from Python on OS X 10.5 by following the instructions at this blog post. If you&#8217;re using Pydev in Eclipse, be sure /Library/Python/2.5/site-packages is in the System PYTHONPATH. Bring up the Preferences dialog, open Pydev in the [...]]]></description>
			<content:encoded><![CDATA[<p>It was more work than it should have been, but you can get access to a MySQL database from Python on OS X 10.5 by following the instructions <a href="http://www.shannymusings.com/2007/10/29/os-x-10-5-python-and-mysqldb/">at this blog post</a>.</p>

<p>If you&#8217;re using Pydev in Eclipse, be sure /Library/Python/2.5/site-packages is in the System PYTHONPATH. Bring up the Preferences dialog, open Pydev in the tree, click on Interpreter &#8211; Python, click New Folder to the right of System PYTHONPATH, and then add the directory, if necessary.</p>

<p><strong>Update 12/27/2009:</strong> With MySQL 5.1.41 and Snow Leopard (OS X 10.6), you no longer need to create the lib/mysql directory with symbolic links as described in the above article. Also, since Snow Leopard comes with Python 2.6, the path above for Eclipse should be <code>/Library/Python/2.6/site-packages</code>. I found <a href="http://geert.vanderkelen.org/2009/09/mysql-python-and-macos-x-106-snow.html">Geert&#8217;s instructions</a> to be quite helpful for Snow Leopard. There&#8217;s also a lot of useful info <a href="http://cd34.com/blog/programming/python/mysql-python-and-snow-leopard/">here</a>.</p>

<p>One problem I ran into is that I initially built the MySQL Python connector with a 32-bit version of MySQL 5.1 installed. After upgrading, I forgot to delete the build directory to force the connector to completely rebuild. When I then tried to run &#8220;import MySQLdb&#8221; in the interpreter, I got the cryptic message &#8220;ImportError: dynamic module does not define init function (init_mysql)&#8221;. If I had read all of the comments in that last article before figuring this out, I might have gotten a hint from the comment mentioning that not even &#8220;setup.py clean&#8221; would delete the build directory if you left off the 64-bit architecture flags.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.wombatnation.com/2008/02/mysql-support-from-python-on-os-x/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

