<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>I am Philipp Keller, leading the online operations team at local.ch. I still like to hack in python. For further details see my public linkedin profile.</description><title>Random Howtos</title><generator>Tumblr (3.0; @coderandom)</generator><link>http://howto.pui.ch/</link><item><title>How to increase blog traffic</title><description>&lt;a href="http://www.seomoz.org/blog/21-tactics-to-increase-blog-traffic-2012"&gt;How to increase blog traffic&lt;/a&gt;: &lt;p&gt;Trying out a few of those tips. Having problems with “#1 Target Your Content to an Audience Likely to Share”.&lt;/p&gt;
&lt;p&gt;There are some tumblr specific tips &lt;a href="http://nerdramblings.tumblr.com/post/4388960162/how-to-increase-you-tumblr-seo"&gt;here&lt;/a&gt;&lt;/p&gt;</description><link>http://howto.pui.ch/post/39770866173</link><guid>http://howto.pui.ch/post/39770866173</guid><pubDate>Sat, 05 Jan 2013 15:54:00 -0500</pubDate></item><item><title>Tutorial: Django on Appengine using Google Cloud SQL - Adaptations for Python 2.5</title><description>&lt;p&gt;Google App Engine has two Python runtimes, &lt;a href="https://developers.google.com/appengine/docs/whatisgoogleappengine#The_Application_Environment"&gt;either 2.7.3 or 2.5.2&lt;/a&gt;. You should try to develop for 2.7, as it&amp;#8217;s the current default on GAE and all the documentations often only describe this Python version.&lt;/p&gt;
&lt;p&gt;Additionally: If you use Python 2.5 you can only use Django up to version 1.3. (At least I couldn&amp;#8217;t find out how to get version 1.4 working, &lt;code&gt;use_library('django', '1.3')&lt;/code&gt; would fail if setting 1.4&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re stuck with Python below 2.7 for any reason, that&amp;#8217;s what you need to change following &lt;a href="http://howto.pui.ch/post/39245389801/tutorial-django-1-4-on-appengine-using-google-cloud"&gt;my tutorial&lt;/a&gt; in order to get it working for Python 2.5:&lt;/p&gt;
&lt;!-- more --&gt;
&lt;ol&gt;&lt;li&gt;
  If you&amp;#8217;re Python version is 2.6, you need to get a 2.5 enviroment: either using virtualenv: &lt;pre&gt;virtualenv -p /usr/bin/python2.5&lt;/pre&gt;
  or simply change the default python version:&lt;br/&gt;
  OS X: &lt;pre&gt;defaults write com.apple.versioner.python Version 2.5&lt;/pre&gt;
  Linux: &lt;pre&gt;ln -f /usr/bin/python2.6 /usr/local/bin/python&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;In order to make oauth work you need to install ssl (which comes preinstalled with 2.7): &lt;pre&gt;sudo /usr/bin/python2.5 /usr/local/bin/pip install ssl&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Instead of &lt;code&gt;app.yaml&lt;/code&gt; &lt;a href="http://howto.pui.ch/post/39245389801/tutorial-django-1-4-on-appengine-using-google-cloud#create_the_django_project"&gt;defined in the tutorial&lt;/a&gt; you need to put 2 files into your project dir: app.yaml and main.py:&lt;br/&gt;&lt;code&gt;app.yaml&lt;/code&gt; (replace &lt;code&gt;appproject&lt;/code&gt; with the id of your appspot.com instance):
&lt;pre&gt;
application: appproject
version: 1
runtime: python
api_version: 1

handlers:
- url: /static/admin
  static_dir: static/admin
  expiration: '0'
- url: /.*
  script: main.py
&lt;/pre&gt;
&lt;code&gt;main.py&lt;/code&gt; (normally those main.py snippets in the web set &lt;code&gt;DJANGO_SETTINGS_MODULE&lt;/code&gt; to &lt;code&gt;mysite.settings&lt;/code&gt;, but in my enviroment it only worked when omitting the project name):
&lt;pre&gt;
import os
import sys
import logging
 
# Google App Hosting imports.
from google.appengine.ext.webapp import util
from google.appengine.dist import use_library
 
os.environ["DJANGO_SETTINGS_MODULE"] = "settings"
 
use_library('django', '1.3')
 
# Enable info logging by the app (this is separate from appserver's
# logging).
logging.getLogger().setLevel(logging.DEBUG)
 
def log_exception(*args, **kwds):
  logging.exception('Exception in request:')
 
# Force sys.path to have our own directory first, so we can import from it.
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
 
# Force Django to reload its settings.
from django.conf import settings
settings._target = None
 
import django.core.handlers.wsgi
import django.core.signals
import django.db
 
# Log errors.
django.dispatch.Signal.connect(
   django.core.signals.got_request_exception, log_exception)
 
# Unregister the rollback event handler.
django.dispatch.Signal.disconnect(
django.core.signals.got_request_exception,
django.db._rollback_on_exception)
 
def main():    
    # Create a Django application for WSGI.
    application = django.core.handlers.wsgi.WSGIHandler()
 
    # Run the WSGI CGI handler with that application.
    util.run_wsgi_app(application)
 
if __name__ == "__main__":
    main()
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;That&amp;#8217;s it, the rest of the tutorial should work!&lt;/li&gt;
&lt;/ol&gt;&lt;h3&gt;Troubleshooting&lt;/h3&gt;
&lt;strong&gt;I get &lt;code&gt;pkg_resources.DistributionNotFound: pip==0.8&lt;/code&gt; when trying to pip install&lt;/strong&gt;
&lt;p&gt;Run this first:
&lt;/p&gt;&lt;pre&gt;sudo easy_install --upgrade pip&lt;/pre&gt;</description><link>http://howto.pui.ch/post/39406024646</link><guid>http://howto.pui.ch/post/39406024646</guid><pubDate>Tue, 01 Jan 2013 15:53:00 -0500</pubDate><category>django</category><category>python 2.5</category><category>google app engine</category><category>main.py</category></item><item><title>Tutorial: Django on Appengine using Google Cloud SQL</title><description>&lt;p&gt;&lt;img src="https://lh5.googleusercontent.com/-lX6aq3qvV50/UOC0ONuosVI/AAAAAAAAMUE/Q_occPtbmnQ/s230/Untitled-1.png" align="right"/&gt;
Google is running an &lt;a href="https://developers.google.com/cloud-sql/docs/billing#intro_trial"&gt;introductory trial for Cloud SQL that runs since Nov 2012 until June 1, 2013&lt;/a&gt;. That&amp;#8217;s the right hour to test Django on Google App Engine. No need to mess around with their non relational datastore. Just use their MySQL 5.5 in the cloud.
&lt;/p&gt;

&lt;p&gt;Hence I decided to give it a try and documented all into a very complete tutorial how to start a Django 1.4 project running on &amp;#8220;Google App Engine&amp;#8221;.&lt;/p&gt;&lt;!-- more --&gt;
&lt;p&gt;If you run into exceptions, check the troubleshooting part at the bottom&lt;/p&gt;

&lt;h1 id="requirements"&gt;Requirements&lt;/h1&gt;
&lt;ul&gt;&lt;li&gt;Python 2.7. If you can&amp;#8217;t use 2.7 for any reason, no worries. &lt;a href="http://howto.pui.ch/post/39406024646/tutorial-django-on-appengine-using-google-cloud-sql"&gt;Here are the adaptions&lt;/a&gt; you need to make for this tutorial to work&lt;/li&gt;
  &lt;li&gt;OS X or Linux. I&amp;#8217;m on OS X 10.8.2, I marked the steps that are OS X specific. For Linux users it&amp;#8217;s most probably very easy to adapt those. For Windows you certainly need to do some bigger adaptations.&lt;/li&gt;
  &lt;li&gt;MySQL and its python bindings (for local development): &lt;a href="http://howto.pui.ch/post/39213978701/how-to-install-mysql-and-python-bindings-on-os-x"&gt;detailed instructions for OS X here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;What about Django &amp;lt; 1.4?&lt;/h2&gt;
&lt;p&gt;Appengine supports the versions 0.96, 1.2, 1.3 and 1.4. This tutorial should work with all those versions. I only tested 1.3 and 1.4 though.
All you need to do with this tutorial is to change 1.4 to 1.3 and keep in mind that the &lt;a href="https://docs.djangoproject.com/en/dev/releases/1.4/#updated-default-project-layout-and-manage-py"&gt;Django directory structure slightly changed&lt;/a&gt; in version 1.4 so you need to adapt some of the shell commands.&lt;/p&gt;


&lt;h1 id="create_google_app_engine_instance"&gt;Create a Google App Engine Instance&lt;/h1&gt;
&lt;p&gt;
  Create new instance on &lt;a href="https://appengine.google.com/"&gt;appengine&lt;/a&gt;.&lt;br/&gt;
  Your instance will be located in the US unless you&amp;#8217;re willing to pay &lt;a href="https://cloud.google.com/pricing/"&gt;500$ a month to register for a premium account&lt;/a&gt;
  (Europe hosting is &lt;a href="https://developers.google.com/appengine/docs/premier/location"&gt;for premium accounts only&lt;/a&gt;)
&lt;/p&gt;

&lt;h1 id="install_gae"&gt;Install Google App Engine (OS X specific)&lt;/h1&gt;
&lt;ol&gt;&lt;li&gt;Download the &lt;a href="https://developers.google.com/appengine/downloads#Google_App_Engine_SDK_for_Python"&gt;GoogleAppEngineLauncher-x.x.x.dmg&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Open the dmg, move &lt;code&gt;GoogleAppEngineLauncher&lt;/code&gt; to Applications&lt;/li&gt;
  &lt;li&gt;Open GoogleAppEngineLauncher, say yes to the symlinks&lt;/li&gt;
  &lt;li&gt;
    Add &lt;code&gt;$PATH&lt;/code&gt; and &lt;code&gt;$PYTHONPATH&lt;/code&gt; to shell environment: Add these lines to &lt;code&gt;.bash_profile&lt;/code&gt; (&lt;code&gt;.bashrc&lt;/code&gt; on Linux):
    &lt;pre&gt;
export GAE="/usr/local/google_appengine"
export PYTHONPATH="$PYTHONPATH:$GAE:$GAE/lib/django_1_4"
export PATH=${PATH}:$GAE/lib/django_1_4/django/bin/&lt;/pre&gt;Load these settings into the current session with &lt;pre&gt;source ~/.bash_profile&lt;/pre&gt; and make the django binaries executable: &lt;pre&gt;chmod a+x $GAE/lib/django_1_4/django/bin/[a-z]*.py&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;&lt;h1 id="create_the_django_project"&gt;Create the django project&lt;/h1&gt;
&lt;ol&gt;&lt;li&gt;
    run this in a directory of your choice (I chose &lt;code&gt;~/python/&lt;/code&gt;). This generates a stub django project. Replace mysite with the name of your django project. &lt;pre&gt;django-admin.py startproject mysite&lt;/pre&gt;Switch into mysite (where &lt;code&gt;manage.py&lt;/code&gt; resides, only do this if you run Django 1.4):&lt;pre&gt;cd mysite&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    create the file &lt;code&gt;mysite/app.yaml&lt;/code&gt; with this content (replace &lt;code&gt;appproject&lt;/code&gt; with the id of your appspot.com instance):
&lt;pre&gt;
application: appproject
version: 1
runtime: python27
api_version: 1
threadsafe: true

libraries:
- name: django
  version: "1.4"

builtins:
- django_wsgi: on

handlers:
- url: /static/admin
  static_dir: static/admin
  expiration: '0'
&lt;/pre&gt;
&lt;br/&gt;&lt;/li&gt;
&lt;li&gt;edit &lt;code&gt;mysite/settings.py&lt;/code&gt;: Change the value of &lt;code&gt;ROOT_URLCONF&lt;/code&gt; from &lt;code&gt;mysite.urls&lt;/code&gt; to &lt;code&gt;urls&lt;/code&gt; (else you run into an exception in your live instance)&lt;/li&gt;
&lt;li&gt;also in &lt;code&gt;settings.py&lt;/code&gt; add these 2 lines anywhere at the top:
&lt;pre&gt;
import os
BASE_DIR = os.path.abspath(os.path.dirname(__file__)) + os.sep
&lt;/pre&gt;
This is the path prefix you&amp;#8217;ll put before all the &lt;code&gt;xyz_ROOT&lt;/code&gt; settings later.&lt;/li&gt;
&lt;li&gt;run this one level up of your python project directory: &lt;pre&gt;dev_appserver.py mysite&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Congrats! Your &lt;a href="http://localhost:8080"&gt;local instance&lt;/a&gt; now shows &lt;a href="http://i.imgur.com/rXh74.png"&gt;this&lt;/a&gt; - hopefully :-)&lt;/p&gt;

&lt;h1 id="set_up_google_cloud_sql"&gt;Set up Google Cloud SQL&lt;/h1&gt;
&lt;ol&gt;&lt;li&gt;Register Cloud SQL in the &lt;a href="https://code.google.com/apis/console/"&gt;Google API Console&lt;/a&gt; (I think you need to add billing, but currently there&amp;#8217;s a free plan until June 1, 2013)&lt;/li&gt;
&lt;li&gt;create a new instance in the &lt;strong&gt;United States&lt;/strong&gt; (even when you&amp;#8217;re located in Europe). The reason is that your Cloud SQL instance needs to be at the same location as your GAE instance. Put your ID of your appspot.com instance to the Authorized Applications.&lt;/li&gt;
&lt;li&gt;create a new database using the SQL Prompt: &lt;pre&gt;CREATE DATABASE my_database;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;replace the &lt;code&gt;DATABASES&lt;/code&gt; section of your &lt;code&gt;settings.py&lt;/code&gt; with the snippet below: (Replace &lt;code&gt;my_project:instance1&lt;/code&gt; with your Cloud SQL Instance id and &lt;code&gt;my_database&lt;/code&gt; with your created database name).
&lt;pre&gt;
import os
if (os.getenv('SERVER_SOFTWARE', '').startswith('Google App Engine') or
    os.getenv('SETTINGS_MODE') == 'prod'):
    # Running on production App Engine, so use a Google Cloud SQL database.
    DATABASES = {
        'default': {
            'ENGINE': 'google.appengine.ext.django.backends.rdbms',
            'INSTANCE': 'my_project:instance1',
            'NAME': 'my_database',
        }
    }
else:
    # Running in development, so use a local MySQL database
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'USER': 'root',
            'PASSWORD': '',
            'HOST': 'localhost',
            'NAME': 'my_db',
        }
    }
&lt;/pre&gt;
These settings configure django to use a local MySQL storage for development. That&amp;#8217;s very close to the cloud setup, as Google Cloud SQL is &lt;a href="https://developers.google.com/cloud-sql/faq#databaseengine"&gt;powered by Mysql (currently 5.5)&lt;/a&gt;&lt;br/&gt;
I highly recommend this as on my machine every SQL query took about 1 second when run against Google Cloud SQL.&lt;br/&gt;
That comes from the fact as first the SQL queries run over HTTP and second the Cloud SQL Instance &lt;a href="https://ipdb.at/ip/74.125.132.95"&gt;runs in California&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;To trigger the oauth authorization (stored in &lt;code&gt;~/.googlesql_oauth2.dat&lt;/code&gt;) run this:&lt;pre&gt;SETTINGS_MODE='prod' python manage.py syncdb&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;If that last command worked that proves that your Cloud SQL worked so far. Congrats!&lt;/p&gt;
&lt;p&gt;Your local MySQL instance is now ready as well. You should check if &lt;code&gt;MySQLdb&lt;/code&gt; is installed:
&lt;/p&gt;&lt;pre&gt;python -c "import MySQLdb"&lt;/pre&gt;
To test the Django↔MySQL connection run
&lt;pre&gt;python mysite/manage.py syncdb&lt;/pre&gt;

&lt;p&gt;Whenever you want to sync your django models to:&lt;br/&gt;
a) the &lt;em&gt;live&lt;/em&gt; db: &lt;code&gt;SETTINGS_MODE='prod' python manage.py syncdb&lt;/code&gt;&lt;br/&gt;
b) the &lt;em&gt;local mysql&lt;/em&gt; db: &lt;code&gt;python manage.py syncdb&lt;/code&gt;&lt;/p&gt;

&lt;h1 id="deploy_your_stub_app_to_appspot"&gt;Deploy your stub app to appspot&lt;/h1&gt;
&lt;p&gt;
  Ready to deploy your fresh app to the cloud?&lt;br/&gt;
  Run this (replace mysite with your project name): &lt;/p&gt;&lt;pre&gt;appcfg.py --oauth2 update mysite&lt;/pre&gt;&lt;br/&gt;
  After about 1 minute your fresh Django project should run perfectly on &lt;a href="http://your-id.appspot.com/"&gt;http://your-id.appspot.com/&lt;/a&gt;


&lt;p&gt;&lt;br/&gt;&lt;strong&gt;Why not sqlite?&lt;/strong&gt;&lt;br/&gt;
Sqlite would be a lot easier to set up, actually there is nothing to install and no server to start, no passwords, etc.&lt;br/&gt;
Apart from the fact that I couldn&amp;#8217;t get it working (details see &lt;a href="http://stackoverflow.com/questions/14080430"&gt;here&lt;/a&gt;) it&amp;#8217;s certainly not a smart idea to run sqlite locally and MySQL (as used by Cloud SQL) in production, &lt;a href="http://stackoverflow.com/questions/2306048/django-sqlite-for-dev-mysql-for-prod"&gt;it&amp;#8217;s very likely that you&amp;#8217;ll run into issues&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id="serve_static_files"&gt;Serving static files&lt;/h1&gt;

&lt;p&gt;Django &lt;a href="https://docs.djangoproject.com/en/dev/howto/static-files/"&gt;supports serving static files&lt;/a&gt; via &lt;code&gt;django.contrib.staticfiles&lt;/code&gt;. However, I didn&amp;#8217;t get this to work. And since serving these files directly via GAE is faster anyways, add this to your &lt;code&gt;app.yaml&lt;/code&gt;:

&lt;/p&gt;&lt;pre&gt;
- url: /media
  static_dir: media
  expiration: '0'
&lt;/pre&gt;

&lt;p&gt;This assumes your static files are under &lt;code&gt;mysite/media&lt;/code&gt;. Your static files now serve under &lt;a href="http://localhost:8080/media/"&gt;/media/&lt;/a&gt;&lt;/p&gt;

&lt;h1 id="enable_admin_optional"&gt;Enable Admin (optional)&lt;/h1&gt;

&lt;p&gt;You probably want to enable the admin interface (Steps 2-4 are actually all about getting the static admin files to serve. Full discussion see &lt;a href="http://stackoverflow.com/questions/9860610"&gt;here&lt;/a&gt;.)&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;
    Uncomment all admin specific lines in &lt;code&gt;settings.py&lt;/code&gt; (in &lt;code&gt;INSTALLED_APPS&lt;/code&gt;) and &lt;code&gt;urls.py&lt;/code&gt; (header and urlpatterns).&lt;br/&gt;
    Go sure you don&amp;#8217;t miss any of these lines by double checking &lt;a href="https://docs.djangoproject.com/en/1.3/intro/tutorial02/#activate-the-admin-site"&gt;here, under &amp;#8220;Activate the admin site&amp;#8221;&lt;/a&gt;.
  &lt;/li&gt;
  &lt;li&gt;Sync the new models agains live&lt;pre&gt;SETTINGS_MODE='prod' python mysite/manage.py syncdb&lt;/pre&gt;and local MySQL&lt;pre&gt;python mysite/manage.py syncdb&lt;/pre&gt;&lt;/li&gt;
  &lt;li&gt;
    in &lt;code&gt;settings.py&lt;/code&gt; replace the &lt;code&gt;STATIC_ROOT&lt;/code&gt; line with (you defined BASE_DIR &lt;a href="#create_the_django_project"&gt;above&lt;/a&gt;):
    &lt;pre&gt;STATIC_ROOT = BASE_DIR + 'static'&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    To copy all the admin media assets into &lt;code&gt;mysite/static&lt;/code&gt; run:
    &lt;pre&gt;python mysite/manage.py collectstatic&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;now, &lt;a href="http://localhost:8080/admin/"&gt;/admin&lt;/a&gt; should show your admin site, with CSS.&lt;/li&gt;
&lt;/ol&gt;&lt;h1 id="and_now"&gt;And now?&lt;/h1&gt;

&lt;ul&gt;&lt;li&gt;If you&amp;#8217;re new to Django or if you want to be 100% sure everything works as expected follow the &lt;a href="https://docs.djangoproject.com/en/1.4/intro/tutorial01/"&gt;django tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Want to port your Django app to Google App Engine? I&amp;#8217;ll likely come up with another article about that.&lt;/li&gt;
&lt;/ul&gt;&lt;h1 id="troubleshooting"&gt;Troubleshooting&lt;/h1&gt;

&lt;strong&gt;on my development machine the web app is &lt;em&gt;veeery&lt;/em&gt; slow&lt;/strong&gt;&lt;br/&gt;&lt;p&gt;Chances are high that you&amp;#8217;re not using the local MySQL. Start dev_appserver.py with the &lt;code&gt;--debug&lt;/code&gt; flag and see if it does any RPC calls (SQL queries wrapped into HTTP)&lt;/p&gt;
&lt;p&gt;If that isn&amp;#8217;t the issue you might want to &lt;a href="https://developers.google.com/appengine/docs/python/tools/appstats#EventRecorders"&gt;track performance with appstats&lt;/a&gt;.&lt;/p&gt;

&lt;strong&gt;I wanted to use sqlite instead of mysql as a backend, but I run into &lt;code&gt;ImportError&lt;/code&gt;, &lt;code&gt;cannot import name utils&lt;/code&gt;&lt;/strong&gt;
&lt;p&gt;So did I. I don&amp;#8217;t know how to solve it. See &lt;a href="http://stackoverflow.com/questions/14080430"&gt;here&lt;/a&gt; for details.&lt;/p&gt;

&lt;strong&gt;I get an &lt;code&gt;unknown locale&lt;/code&gt; exception when running syncdb against MySQL&lt;/strong&gt;
&lt;p&gt;I personally got &lt;code&gt;ValueError: unknown locale: UTF-8&lt;/code&gt;. There is a &lt;a href="http://patrick.arminio.info/blog/2012/02/fix-valueerror-unknown-locale-utf8/"&gt;solution for that&lt;/a&gt;&lt;/p&gt;

&lt;strong&gt;I get a &lt;code&gt;DoesNotExist&lt;/code&gt; exception when accessing /admin/&lt;/strong&gt;
&lt;p&gt;At one point I got this exception: &lt;code&gt;DoesNotExist at /admin/&lt;/code&gt;, &lt;code&gt;Site matching query does not exist&lt;/code&gt;&lt;br/&gt;
Solution is &lt;a href="http://stackoverflow.com/questions/9736975/django-admin-doesnotexist-at-admin"&gt;described here&lt;/a&gt;&lt;/p&gt;

&lt;strong&gt;I get an ImportError for mysite.urls&lt;/strong&gt;
&lt;p&gt;I got the exception &lt;code&gt;No module named mysite.urls&lt;/code&gt; before I replaced
&lt;/p&gt;&lt;pre&gt;ROOT_URLCONF = 'mysite.urls'&lt;/pre&gt;
with
&lt;pre&gt;ROOT_URLCONF = 'urls'&lt;/pre&gt;
I didn&amp;#8217;t really understand why that error occurs.


&lt;h1 id="other_older_tutorials"&gt;Further reading&lt;/h1&gt;
&lt;strong&gt;Official documentation&lt;/strong&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="https://developers.google.com/appengine/docs/python/cloud-sql/django"&gt;Official Google Documentation on how to use Django with Google Cloud SQL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;strong&gt;Other tutorials&lt;/strong&gt;
&lt;ul&gt;&lt;li&gt;Google App Engine, Django and Cloud SQL &lt;a href="http://bjornalycke.se/articles/google-app-engine-django-and-cloud-sql"&gt;Part 1&lt;/a&gt; and &lt;a href="http://bjornalycke.se/articles/google-app-engine-django-and-cloud-sql-part-ii"&gt;2&lt;/a&gt; (Björnalycke)&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.joemartaganna.com/web-development/running-django-13-in-google-app-engine-with-google-cloud-sql/"&gt;Running Django 1.3 in Google App Engine with Google Cloud SQL (Joemar Taganna)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;strong&gt;Outdated tutorials (based on Datastore, e.g. django-nonrel)&lt;/strong&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://thomas.broxrost.com/2008/04/08/django-on-google-app-engine/"&gt;Django on Google App Engine in 13 simple steps (by Thomas Brox Røst)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://agiliq.com/blog/2008/04/two-djangoappengine-tutorials/"&gt;Using Django with Appengine (2 tutorials by Shabda Raaj)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><link>http://howto.pui.ch/post/39245389801</link><guid>http://howto.pui.ch/post/39245389801</guid><pubDate>Sun, 30 Dec 2012 16:47:00 -0500</pubDate><category>django</category><category>appengine</category><category>google cloud sql</category><category>python</category><category>mysql</category></item><item><title>How to install mysql and python bindings on OS X</title><description>&lt;p&gt;For my upcoming post &lt;a href="http://howto.pui.ch/post/39245389801/tutorial-django-on-appengine-using-google-cloud-sql"&gt;&amp;#8220;how to create a Django project on Google App Engine&amp;#8221;&lt;/a&gt; I needed to install a MySQL instance and configure python to do so.
MySQL is a little beast, and it is not so straight forward to install it on OS X&amp;#8230;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;ol&gt;&lt;li&gt;
    Install mysql. Find good instructions &lt;a href="http://www.djangoapp.com/blog/2011/07/24/installation-of-mysql-server-on-mac-os-x-lion/"&gt;here&lt;/a&gt;. I also did the optional step to install the MySQL startup scripts and preference pane. I know I&amp;#8217;ll forget how to start the mysql server manually after 2 months, so the entry in &lt;code&gt;System Preferences&lt;/code&gt; is handy.
  &lt;/li&gt;
  &lt;li&gt;
    create your database: &lt;pre&gt;mysql -u root -e "CREATE DATABASE my_db;"&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    Optionally set a password for root (I left it blank as my local mysql server only serves to localhost):&lt;br/&gt;&lt;pre&gt;
      $ mysql -u root
      mysql&amp;gt; use mysql;
      mysql&amp;gt; update user set password=PASSWORD("NEWPASSWORD") where User='root';
      mysql&amp;gt; flush privileges;
      mysql&amp;gt; quit
    &lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    Install MySQLdb (the mysql python binding): &lt;pre&gt;sudo pip install MySQL-python&lt;/pre&gt; If you haven&amp;#8217;t yet installed &lt;code&gt;pip&lt;/code&gt;: &lt;pre&gt;sudo easy_install pip&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;Test it: &lt;pre&gt;python -c "import MySQLdb"&lt;/pre&gt; should output no error.&lt;/li&gt;
&lt;/ol&gt;&lt;h3&gt;Troubleshooting&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;&lt;code&gt;Library not loaded: libmysqlclient.18.dylib&lt;/code&gt;, &lt;code&gt;Reason: image not found&lt;/code&gt;. Solution: &lt;pre&gt;sudo ln -s /usr/local/mysql/lib/libmysqlclient.18.dylib /usr/lib/libmysqlclient.18.dylib&lt;/pre&gt; as described &lt;a href="http://stackoverflow.com/questions/6383310"&gt;here&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;code&gt;IOError: [Errno 13] file not accessible: '/Library/Python/2.7/site-packages/MySQL_python-1.2.3-py2.7-macosx-10.8-intel.egg'&lt;/code&gt;. I ran into this problem when building &lt;code&gt;MySQL-python&lt;/code&gt; myself. &lt;pre&gt;pip install MySQL-python&lt;/pre&gt; solved this problem
  &lt;/li&gt;
  &lt;li&gt;&lt;p&gt;on &lt;code&gt;pip install MySQL-python&lt;/code&gt; I got &lt;code&gt;EnvironmentError: mysql_config not found&lt;/code&gt;&lt;/p&gt;
  Before running pip, run this
  &lt;pre&gt;export PATH=$PATH:/usr/local/mysql/bin&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;</description><link>http://howto.pui.ch/post/39213978701</link><guid>http://howto.pui.ch/post/39213978701</guid><pubDate>Sun, 30 Dec 2012 08:45:00 -0500</pubDate><category>mysql</category><category>python</category><category>MySQLdb</category></item><item><title>How to migrate your wordpress to tumblr. Including images and comments.</title><description>&lt;p&gt;&lt;img src="https://lh3.googleusercontent.com/-Pn-aBqMjq9g/UMpMLdyLsgI/AAAAAAAALe0/zbopqqnD77M/s300/wordpresstumblr.jpg" align="right"/&gt;So I&amp;#8217;ve decided to move my wordpress blogs to tumblr. Although apparently TechCrunch &lt;a href="http://techcrunch.com/2010/09/18/stuff-white-person-doesnt-like/"&gt;thinks that&amp;#8217;s a bad idea&lt;/a&gt;. And although &lt;a href="https://twitter.com/moritzadler"&gt;Moritz Adler&lt;/a&gt; would kill me for that. (Although: He doesn&amp;#8217;t have a personal blog and hence has no licence to kill me). Anyway. With tumblr I don&amp;#8217;t need to host a blog software myself. And I don&amp;#8217;t end up having my blog hacked and then seeing my blog being displayed as a malware site in Chrome/Firefox (happened to me twice). And then with tumblr I create new blogs with subdomains within minutes. Cool stuff. Hail to the cloud, baby!&lt;/p&gt;
&lt;p&gt;So here you go: A complete guide how to fully migrate your wordpress blog to tumblr. Including comments and pictures. And still supporting your old url scheme.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I ran into a tool that claims to do a lot for you: &lt;a href="http://www.import2.com/tumblr"&gt;import2.com/tumblr&lt;/a&gt;. It doesn&amp;#8217;t migrate images and 302 redirects. Not sure about comments migration. And it costs 24$. Still, if you can leave out some of the steps below that&amp;#8217;d be worth the money. &lt;a href="http://www.quora.com/Mark-Kofman/answers/Tumblr"&gt;Comments of the author on quora&lt;/a&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="beforeyoustart"&gt;Before you start&lt;/h2&gt;
&lt;p&gt;Before you start to actually move your blog, you need to consider a few things:&lt;/p&gt;

&lt;h3&gt;Where do you move your &lt;strong&gt;DNS&lt;/strong&gt; to?&lt;/h3&gt;
&lt;p&gt;If you have a wordpress webhost, then this webhost most probably also does DNS for you. You need to replace that by a third party solution. I think these are good services:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="https://dns.he.net/"&gt;he.net&lt;/a&gt;. Free service. No strings attached. The one I&amp;#8217;ve chosen. The interface is nice and very easy to add new CNAMES, MX records, etc. The uptime was &lt;a href="http://www.lowendtalk.com/discussion/262/which-dns-site-to-use-for-domains#Comment_3800"&gt;reported to be not so good&lt;/a&gt;, but I don&amp;#8217;t really care about uptime of my blogs. To host your tumblr blog on your domain, you add a &lt;code&gt;CNAME&lt;/code&gt; to &lt;code&gt;domains.tumblr.com&lt;/code&gt; and then configure your tumblr blog to listen to that domain. Very simple.&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://aws.amazon.com/route53/"&gt;Amazon Route 53&lt;/a&gt;: They charge you $0.50 per hosted zone per month. That&amp;#8217;s a fair price and probably has a better uptime then he.net&lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;What do you want to do with your &lt;strong&gt;images&lt;/strong&gt;?&lt;/h3&gt;

&lt;p&gt;At default they&amp;#8217;re all located under &lt;code&gt;&lt;a href="http://www.yourolddomain.com/wp-content/img1.jpg"&gt;www.yourolddomain.com/wp-content/img1.jpg&lt;/a&gt;&lt;/code&gt;. To completely get rid of your old web host you need to move those to a different image hoster. I don&amp;#8217;t advice you to upload it to tumblr because if in future you want to move away from tumblr you run into the same problem again.&lt;/p&gt;

&lt;h3&gt;Would you like to keep your &lt;strong&gt;comments&lt;/strong&gt;?&lt;/h3&gt;
&lt;p&gt;Do you have comments at all? Tumblr doesn&amp;#8217;t support comments by itself. Most themes have disqus support. Moving comments to disqus is no big deal, but still it&amp;#8217;s some work, so you may decide to just not migrate comments.&lt;/p&gt;
  
&lt;h3&gt;Are you keen to not break your &lt;strong&gt;old blog urls&lt;/strong&gt;?&lt;/h3&gt;
&lt;p&gt;Wordpress&amp;#8217; url scheme generally is e.g. &lt;code&gt;code.pui.ch/2007/01/05/print-hello-world/&lt;/code&gt;.&lt;br/&gt;That same post ends up at this tumblr url: &lt;code&gt;howto.pui.ch/post/37471154429/print-hello-world&lt;/code&gt;. Note that the last part of the url is optional, i.e. &lt;code&gt;howto.pui.ch/post/37471154429&lt;/code&gt; works as well.&lt;br/&gt;If you care about incoming links to your blog not to break and if you care about your google ranking (I guess 302 redirects inherit the google ranking), there are two possibilities:
  &lt;/p&gt;&lt;ol style="list-style-type:lower-alpha"&gt;&lt;li&gt;Stay on the same domain, handle the redirects in tumblr (tumblr supports that with the pages&amp;#8217; type &amp;#8220;redirect&amp;#8221;)&lt;/li&gt;
    &lt;li&gt;Move to a different domain and put up e.g. &lt;code&gt;redirect permanent&lt;/code&gt; in a .htaccess file on your web server&lt;/li&gt;
  &lt;/ol&gt;&lt;h2&gt;A rough outline of what you&amp;#8217;re up to&lt;/h2&gt;
At a glance, that what you&amp;#8217;ll do:
&lt;ol&gt;&lt;li&gt;Upload your images to a different hoster (if you want to get rid of your old webhost)&lt;/li&gt;
  &lt;li&gt;Extract all blog posts+comment from wordpress&lt;/li&gt;
  &lt;li&gt;Fix the export.xml: Replace images, more-tags and fix some additional stuff&lt;/li&gt;
  &lt;li&gt;Migrate your wordpress blog to blogger&lt;/li&gt;
  &lt;li&gt;Migrate your blogger blog to tumblr&lt;/li&gt;
  &lt;li&gt;Install http redirects (on old webhost or on tumblr)&lt;/li&gt;
  &lt;li&gt;Migrate your comments to disqus&lt;/li&gt;
  &lt;li&gt;Clean up blog posts (might be a biggie if you&amp;#8217;re a perfectionist)&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Alright, let&amp;#8217;s specify those 8 steps.&lt;/p&gt;

&lt;h2&gt;Step 1: Upload your images to a different hoster&lt;/h2&gt;
&lt;p&gt;If you&amp;#8217;re ok with keeping your old webhost you can skip this point. Easiest thing to do would be to copy your wp-content directory one to one to a different hoster so &lt;code&gt;&lt;a href="http://www.yourolddomain.com/wp-content/img1.jpg"&gt;www.yourolddomain.com/wp-content/img1.jpg&lt;/a&gt;&lt;/code&gt; turns into &lt;code&gt;&lt;a href="http://www.imagehoster.com/my_user_name/img1.jpg"&gt;www.imagehoster.com/my_user_name/img1.jpg&lt;/a&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t have experience with image hosting providers so I just uploaded my images to picasa, but that meant I needed to update every single image in all my blog posts to the new image url of picasa. That was quite a pain. I couldn&amp;#8217;t find a image hoster yet who meets the criterias above. Photobucket doesn&amp;#8217;t, Dropbox doesn&amp;#8217;t, Google Drive doesn&amp;#8217;t. Maybe Amazon S3&lt;/p&gt;

&lt;h2&gt;Step 2: Extract your blog posts+comment from wordpress&lt;/h2&gt;
&lt;ol&gt;&lt;li&gt;In your wordpress admin go to Tools → Export. On my blog that was &lt;code&gt;code.pui.ch/wp-admin/export.php&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Choose &lt;code&gt;All content&lt;/code&gt;, &lt;code&gt;Download Export File&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;Step 3: Fix the export.xml&lt;/h2&gt;
You have just downloaded an xml file, in my case the name was &lt;code&gt;coderandom.wordpress.2012-12-13.xml&lt;/code&gt;. Open that file with your favourite text editor. Now you need to do a few things before you can go on:
&lt;ol&gt;&lt;li&gt;Replace all &amp;lt;!&amp;#8212;more&amp;#8212;&amp;gt; by &lt;span&gt;[[&lt;/span&gt;MORE&lt;span&gt;]]&lt;/span&gt;. The uppercase actually matters. &lt;span&gt;[[&lt;/span&gt;MORE&lt;span&gt;]]&lt;/span&gt; is the divider that tumblr actually understands as the place where you want your excerpt to stop in the blog overview view.&lt;/li&gt;
&lt;li&gt;Replace all images by the new urls you got by uploading the images to the image hoster in step 1. It&amp;#8217;s much easier to do this at this stage than to replace the images once you&amp;#8217;ve migrated your blog to tumblr.&lt;/li&gt;
&lt;li&gt;You may have more wordpress plugins you used in your posts. I used &lt;code&gt;[python]...[/python]&lt;/code&gt; to syntax highlight my python markup. I&amp;#8217;ve moved to &lt;a href="http://code.google.com/p/google-code-prettify/"&gt;google code prettify&lt;/a&gt; which needs &lt;code&gt;&amp;lt;pre class="prettyprint"&amp;gt;...&amp;lt;/pre&amp;gt;&lt;/code&gt; as a syntax. So I needed to replace all occurrences by the new markup. Obviously, regex is your friend at this stage.&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;Step 4: Migrate your wordpress blog to blogger&lt;/h2&gt;
Unfortunately there&amp;#8217;s no direct way to directly import this xml file into tumblr. Instead, that&amp;#8217;s what you need to do:
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Convert&lt;/strong&gt; your xml file &lt;a href="http://wordpress2blogger.appspot.com/"&gt;on this website&lt;/a&gt; to a file fit for importing into blogger.&lt;br/&gt;
  This doesn&amp;#8217;t work for files bigger than 1MB. If that&amp;#8217;s the case then you can either convert the file on your own machine using &lt;a href="http://code.google.com/p/google-blog-converters-appengine/"&gt;this sourcecode on google code&lt;/a&gt;. Or you can follow the &lt;a href="http://julioinprogress.com/2011/09/10/guide-to-moving-from-wordpress-to-tumblr/"&gt;instructions under step 3 on this blog post.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Create a new blog&lt;/strong&gt; on &lt;a href="http://www.blogger.com"&gt;blogger.com&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;In blogger navigate to your new blog and do settings → other settings → &lt;strong&gt;import blog&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Publish&lt;/strong&gt; all blog posts: Posts → All → Select all → Publish&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;If you have difficulties in this step you might try a different solution (didn&amp;#8217;t try any of these):&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="https://github.com/ideashower/Export-Wordpress-posts-to-Tumblr"&gt;ideashowers PHP script on github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.daveexmachina.com/wordpress/?p=5974"&gt;Dave Lartigues php script (plus explanations)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://dbavaria.tumblr.com/post/28193913/wp2tumblr-transfer-your-blog-from-wordpress-to-tumblr"&gt;Darshan Bavarians PHP script&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://snipplr.com/view/14609/migrate-wordpress-to-tumblr/"&gt;shakefons php script&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Step 5: Migrate your blogger blog to tumblr&lt;/h2&gt;
&lt;ol&gt;&lt;li&gt;Go to &lt;a href="http://www.bloggertotumblr.com/"&gt;bloggertotumblr.com&lt;/a&gt; and enter your url for your newly created blogger and tumblr blogs. The conversion is very straight forward.&lt;/li&gt;
  &lt;li&gt;Delete your blogger blog&lt;/li&gt;
  &lt;li&gt;Enjoy. Your blog posts are now on tumblr. Still missing: Support of the old url scheme and comments&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;Step 6: Install http redirects (on old webhost or on tumblr)&lt;/h2&gt;
&lt;p&gt;In the section &lt;a href="#beforeyoustart"&gt;before you start&lt;/a&gt; I asked you to decide if you&amp;#8217;re ok to break your old urls. If you don&amp;#8217;t care, then skip this step. Although: if you care about keeping your comments then you still might to do this step, as it makes migrating comments to disqus a lot easier&lt;/p&gt;
&lt;p&gt;If you do care, then:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;If you keep the domain of your blog: You need to install tumblr redirect pages. See below.&lt;/li&gt;
  &lt;li&gt;If you changed the domain of your blog: You need to install redirects on your former wordpress webhost. I describe how this is done via .htaccess config below&lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;Install tumblr redirect pages&lt;/h3&gt;
&lt;ol&gt;&lt;li&gt;go to your new tumblr blog&lt;/li&gt;
  &lt;li&gt;click customize top right&lt;/li&gt;
  &lt;li&gt;add a page (left column)&lt;/li&gt;
  &lt;li&gt;instead of &amp;#8220;Standard Layout&amp;#8221; choose &amp;#8220;Redirect&amp;#8221; and add a posts&amp;#8217; old url on top, and the new url on bottom. Repeat this for every blog posts (yeah, lots of work here)&lt;/li&gt;
&lt;/ol&gt;&lt;h3&gt;Install .htaccess on your old webhost&lt;/h3&gt;
&lt;p&gt;IMO that&amp;#8217;s a bit simpler than installing a tumblr redirect for every blog post. Still it&amp;#8217;s a lot of work since you need to come up with a map of old_url → new_url for every blog post. If your webhost supports .htaccess then go for this method. Most probably you have such a file already for your wordpress installation.&lt;/p&gt;
&lt;p&gt;An example of a .htaccess file:&lt;/p&gt;
&lt;pre&gt;
  RewriteEngine On
  Redirect permanent /page/2/ &lt;a href="http://howto.pui.ch/page/2"&gt;http://howto.pui.ch/page/2&lt;/a&gt;
  Redirect permanent /feed/ &lt;a href="http://howto.pui.ch/rss"&gt;http://howto.pui.ch/rss&lt;/a&gt;
  RewriteRule ^$ &lt;a href="http://howto.pui.ch/"&gt;http://howto.pui.ch/&lt;/a&gt; [R=301,L]
  Redirect permanent /2007/02/25/add-bandwidth-to-a-file-download-in-python/ &lt;a href="http://howto.pui.ch/post/37471156141/add-bandwidth-to-a-file-download-in-python"&gt;http://howto.pui.ch/post/37471156141/add-bandwidth-to-a-file-download-in-python&lt;/a&gt;
  Redirect permanent /2007/06/08/python-find-out-cpu-time-of-a-certain-process/ &lt;a href="http://howto.pui.ch/post/37471156554/python-find-out-cpu-time-of-a-certain-process"&gt;http://howto.pui.ch/post/37471156554/python-find-out-cpu-time-of-a-certain-process&lt;/a&gt;
  Redirect permanent /2007/07/23/python-sort-a-list-of-dicts-by-dict-key/ &lt;a href="http://howto.pui.ch/post/37471157116/python-sort-a-list-of-dicts-by-dict-key"&gt;http://howto.pui.ch/post/37471157116/python-sort-a-list-of-dicts-by-dict-key&lt;/a&gt;
  Redirect permanent /2009/12/30/dealing-with-mysql-backend-does-not-support-timezone-aware-datetimes/ &lt;a href="http://howto.pui.ch/post/37471158729/dealing-with-mysql-backend-does-not-support"&gt;http://howto.pui.ch/post/37471158729/dealing-with-mysql-backend-does-not-support&lt;/a&gt;
  Redirect permanent /2011/01/19/python-easy-way-to-show-progress/ &lt;a href="http://howto.pui.ch/post/37471159741/python-easy-way-to-show-progress"&gt;http://howto.pui.ch/post/37471159741/python-easy-way-to-show-progress&lt;/a&gt;
  Redirect permanent /2012/07/17/how-to-detect-a-files-character-encoding/ &lt;a href="http://howto.pui.ch/post/37471161169/how-to-detect-a-files-character-encoding"&gt;http://howto.pui.ch/post/37471161169/how-to-detect-a-files-character-encoding&lt;/a&gt;
  Redirect permanent /2010/04/04/python-display-refreshing-status-like-top/ &lt;a href="http://howto.pui.ch/post/37471159398/python-display-refreshing-status-like-top"&gt;http://howto.pui.ch/post/37471159398/python-display-refreshing-status-like-top&lt;/a&gt;
  Redirect permanent /2011/11/03/how-to-switch-gnu-screen-windows-in-iterm2-via-keyboard-shortcuts/ &lt;a href="http://howto.pui.ch/404"&gt;http://howto.pui.ch/404&lt;/a&gt;
  Redirect permanent /2007/01/19/sched-20-pizza-is-ready/ &lt;a href="http://howto.pui.ch/post/37471155110/sched-20-pizza-is-ready"&gt;http://howto.pui.ch/post/37471155110/sched-20-pizza-is-ready&lt;/a&gt;
&lt;/pre&gt;
&lt;p&gt;Note the first 3 lines, you will need the same for your redirects. Note the special syntax of line 3. That is important to not redirect a non existing url to the new domain.&lt;/p&gt;
&lt;h4&gt;Wait! I just moved my blog away from my old webhost, and now I need to keep it to have http redirects in place?&lt;/h4&gt;
&lt;p&gt;Uh, yes. Alternatively, you can move to a free hoster like google apps engine and e.g. &lt;a href="http://blog.dantup.com/2010/01/generic-redirection-script-for-google-app-engine"&gt;use this&lt;/a&gt; to redirect. Or you just wait a few months and wait until all search engines have digested your redirects and kill your old webhost only then (that&amp;#8217;s what I&amp;#8217;m probably gonna do).&lt;/p&gt;

&lt;h2&gt;Step 7: Migrate your comments to disqus&lt;/h2&gt;
&lt;p&gt;Because tumblr doesn&amp;#8217;t offer comments by itself you need to migrate your comments to disqus:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;a href="http://disqus.com/admin/register/"&gt;Register&lt;/a&gt; your new tumblr blog url at disqus&lt;/li&gt;
  &lt;li&gt;On disqus go to &lt;code&gt;Admin&lt;/code&gt; → &lt;code&gt;Tools&lt;/code&gt; → &lt;code&gt;Import/Export&lt;/code&gt; → &lt;code&gt;Upload WXR&lt;/code&gt;. Choose the XML file you downloaded from your wordpress installation (not that got converted for blogger). Upload that&lt;/li&gt;
  &lt;li&gt;On the same page go to &lt;code&gt;Migrate Threads&lt;/code&gt;. Choose &amp;#8220;Redirect crawler&amp;#8221; if you installed the redirects in step 6. Otherwise you need to use the &amp;#8220;Upload a URL map&amp;#8221; option&lt;/li&gt;
  Install disqus into your tumblr blog: Your tumblr blog → customized (top right). In the left column there should be an option to add your disqus shortname. If there is none, you might consider to change your tumblr theme or &lt;a href="http://help.disqus.com/customer/portal/articles/758168-tumblr-manual-installation-instructions"&gt;install disqus manually into your theme&lt;/a&gt;.
&lt;/ol&gt;&lt;p&gt;Voilà! After a few minutes your comments should appear in your new tumblr blog.&lt;/p&gt;

&lt;h2&gt;Step 8: Clean up your tumblr posts&lt;/h2&gt;
&lt;p&gt;Might be that the html markup of my wordpress posts were so bad, but I needed to fix a lot of spacing between paragraphs. I also had some CSS tweaks to right align the images which I needed to fix.&lt;/p&gt;
&lt;p&gt;Lastly, blogger adds these paragraphs to the end of every blog post:&lt;/p&gt;
&lt;pre&gt;
  &amp;lt;div class="blogger-post-footer"&amp;gt;
    &amp;lt;img alt="" height="1" src="https://blogger.googleusercontent.com/tracker/290349385069691835-5946149615494229188?l=coderandomm.blogspot.com" width="1"&amp;gt;
  &amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;p&gt;If you are a perfectionist you may want to remove this markup from every blog post.&lt;/p&gt;
&lt;p&gt;A word of caution: You can spend a lot of time at this step if you overdo it.&lt;/p&gt;

&lt;h2&gt;Thanks&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Thanks to &lt;strong&gt;MG Siegler&lt;/strong&gt; (one of my favourite bloggers, although he is an Apple fanboy and I am a google disciple): He showed me that you can &lt;a href="http://parislemon.com/post/15604811641/why-i-hate-android"&gt;perfectly write long blog posts on tumblr&lt;/a&gt; (that linked article is actually a must read about Android vs. iPhone)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Julio Angel Ortiz&lt;/strong&gt;, who&amp;#8217;s &lt;a href="http://julioinprogress.com/2011/09/10/guide-to-moving-from-wordpress-to-tumblr/"&gt;article&lt;/a&gt; served as the base for this howto.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;TextMate&lt;/strong&gt; for making html editing so easy. Just found out that it&amp;#8217;s actually a pretty decent HTML editor. I&amp;#8217;ll write my blog posts in here and only then past them into the tiny tumblr HTML editor popup.&lt;/li&gt;
&lt;/ul&gt;</description><link>http://howto.pui.ch/post/37850192094</link><guid>http://howto.pui.ch/post/37850192094</guid><pubDate>Fri, 14 Dec 2012 05:37:00 -0500</pubDate><category>wordpress-to-tumblr</category><category>wordpress</category><category>tumblr</category><category>migration</category></item><item><title>How to fix Jambox' "static noise and no bluetooth sound" problem(includes soldering)</title><description>&lt;div&gt;
  &lt;img alt="fixed!" src="http://i.imgur.com/ofR49.png" style="float: right;"/&gt;&lt;/div&gt;
&lt;p&gt;
  Jambox is a pretty cool device: The sound quality is very good, it is small, it has a battery. I liked it. Until it broke. It just didn&amp;#8217;t play music over bluetooth any more but instead uttered static noise. This seems to be a quite severe production problem as &lt;a href="http://forums.jawbone.com/t5/JAMBOX-Troubleshooting/Static-and-dropping-bluetooth-My-customer-service-call/m-p/37461"&gt;many&lt;/a&gt; &lt;a href="http://forums.jawbone.com/t5/JAMBOX-Troubleshooting/jambox-static-and-airplay/td-p/6676"&gt;many&lt;/a&gt; &lt;a href="http://www.amazon.com/review/R3GYH7DT8H8EKR/ref=cm_cr_pr_cmt?ie=UTF8&amp;amp;ASIN=B004E10KGU"&gt;many&lt;/a&gt; people have devices with the exact same problem. So going down the &amp;#8220;Jambox please replace my device&amp;#8221; way didn&amp;#8217;t sound promising to me. The possibility that the replacement device is broken as well is just too high.
&lt;/p&gt;
&lt;p&gt;
  The problem lies in the aux in port. The device thinks there&amp;#8217;s an aux cable plugged in and outputs the signal from the aux input when in fact it should play the bluetooth sound.
&lt;/p&gt;
&lt;p&gt;
  &lt;!-- more --&gt;In my &lt;a href="http://howto.pui.ch/post/37471160886/how-to-reset-jambox-when-bluetooth-completely-stopped"&gt;last post&lt;/a&gt; I described the different easy-to-do solutions to this problem, but today I needed to implement the soldering solution because nothing else worked. Implementing this solution means tricking the Jambox to think there&amp;#8217;s no aux cable plugged in.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: My initial soldering was working, but after the first recharge the fix stopped working. Might be that the soldering melted and if you are a solder pro this might work for you. Anyway. I personally ended up putting a &lt;a href="http://howto.pui.ch/post/37471160886/how-to-reset-jambox-when-bluetooth-completely-stopped"&gt;screw into the aux port&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;
  &lt;strong&gt;&lt;span&gt;What do you need?&lt;/span&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;a star shaped screw driver (aka torx)
  &lt;/li&gt;
  &lt;li style="list-style: none"&gt;
  &lt;/li&gt;&lt;li&gt;Soldering equipment
  &lt;/li&gt;
  &lt;li style="list-style: none"&gt;
  &lt;/li&gt;&lt;li&gt;being ok that the aux cable will never work again
  &lt;/li&gt;
  &lt;li style="list-style: none"&gt;
  &lt;/li&gt;&lt;li&gt;desparation to get this machine working again (I&amp;#8217;m not sure how safe this is, being not used to that kind of stuff), and of course it will void your warranty
  &lt;/li&gt;
  &lt;li style="list-style: none"&gt;
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;
  I personally hate soldering, I&amp;#8217;m not good at it, but still I managed to get my Jambox working agagin so I thought I&amp;#8217;d share with the world:
&lt;/p&gt;
&lt;h3&gt;
  How to disassemble
&lt;/h3&gt;
&lt;p&gt;
  There&amp;#8217;s &lt;a href="http://www.youtube.com/watch?v=X5APtwqtEps"&gt;a good video describing how it should be done&lt;/a&gt; (I did it just with the screwdriver. No gloves and no other equipment.)&lt;br/&gt;
  You need to follow the video until 5:00
&lt;/p&gt;
&lt;h3&gt;
  What to solder?
&lt;/h3&gt;
&lt;div&gt;
  &lt;img alt="What needs soldering?" src="http://i.imgur.com/cAWlo.jpg" style="float: right;"/&gt;&lt;br/&gt;
  The two metal contacts you need to bridge&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;
&lt;p&gt;
  &lt;br/&gt;&lt;strong&gt;Update&lt;/strong&gt;: David Choi &lt;a href="http://www.youtube.com/watch?v=nd5nF2hSFHw&amp;amp;feature=youtu.be"&gt;has made a video&lt;/a&gt; that shows very well which two contacts to solder. He claims that with good soldering skills you can achieve that both bluetooth and aux will still work. &lt;br/&gt; 
It&amp;#8217;s pretty simple: Follow the aux port and where the end of the aux jack would be there are 2 metal contacts which need to be soldered together. Turn on the jambox and try to push the upper metal contact so the two metal pieces touch and you&amp;#8217;ll hear the bluetooth sound. Hearing the music should give you enough motivation now to go on. Now:
&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Turn off the Jambox
  &lt;/li&gt;
  &lt;li style="list-style: none"&gt;
  &lt;/li&gt;&lt;li&gt;Try to solder (it is tricky because the spot is hard to reach)
  &lt;/li&gt;
  &lt;li style="list-style: none"&gt;
  &lt;/li&gt;&lt;li&gt;Try if it has worked. If it worked, wait some time. Shake the bluetooth device to really go sure the soldering joint is good (first time I was so happy that it worked, I assembled the device again and then it didn&amp;#8217;t work because the soldering joint was flaky)
  &lt;/li&gt;
  &lt;li style="list-style: none"&gt;
&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;
  How to assemble
&lt;/h3&gt;
&lt;div&gt;
  &lt;img alt="Hack" src="http://i.imgur.com/8YeqZ.jpg" style="float: right;"/&gt;I needed to bend the two metal pieces&lt;br/&gt;
  at the end of the grid to be able to assemble it
&lt;/div&gt;
&lt;p&gt;
  Again &lt;a href="http://www.youtube.com/watch?v=X5APtwqtEps&amp;amp;t=10m40s"&gt;follow the video starting from 10:40&lt;/a&gt;.&lt;br/&gt;
  I found the assembling the hardest part. In the end I needed to bend the small metal pieces of the grid to be able to put it back together (although I didn&amp;#8217;t follow the video so you might be more successful).
&lt;/p&gt;
&lt;h3&gt;
  Happy listening
&lt;/h3&gt;
&lt;p&gt;
  My Jambox is now up and running again since 24h. I&amp;#8217;m very very happy that this little thing did the trick.
&lt;/p&gt;</description><link>http://howto.pui.ch/post/37471161448</link><guid>http://howto.pui.ch/post/37471161448</guid><pubDate>Sat, 21 Jul 2012 17:07:00 -0400</pubDate></item><item><title>How to detect a files character encoding</title><description>&lt;p&gt;iconv is alright - except it&amp;#8217;s sometimes hard to know in which encoding the file is I just got.&lt;/p&gt;
&lt;p&gt;There is &lt;a href="http://freecode.com/projects/enca"&gt;enca&lt;/a&gt; which promises to work, but I couldn&amp;#8217;t get it working. I was looking for a simple tool that just outputs the encoding without the need of any parameters&lt;/p&gt;
&lt;p&gt;Now the python module &lt;a href="https://github.com/dcramer/chardet"&gt;chardet&lt;/a&gt; comes to the rescue. Once you have git forked you can write this boilerplate python script &amp;#8220;detect.py&amp;#8221;:&lt;/p&gt;
&lt;pre&gt;#!/usr/bin/python
import sys, chardet
a = open(sys.argv[1]).read()
print chardet.detect(a)
&lt;/pre&gt;
&lt;p&gt;after&lt;br/&gt;&lt;code&gt;chmod a+x detect.py&lt;/code&gt;&lt;br/&gt;you can write:&lt;br/&gt;&lt;code&gt;./detect.py my_strange_file.txt&lt;/code&gt;&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img alt="" height="1" src="https://blogger.googleusercontent.com/tracker/290349385069691835-984568850343921941?l=coderandomm.blogspot.com" width="1"/&gt;&lt;/div&gt;</description><link>http://howto.pui.ch/post/37471161169</link><guid>http://howto.pui.ch/post/37471161169</guid><pubDate>Tue, 17 Jul 2012 03:59:00 -0400</pubDate><category>python</category></item><item><title>How to reset Jambox when bluetooth completely stopped working</title><description>&lt;p&gt;
  I bought a Jambox about half a year ago. Sound wise it is great, but apparently it is not very stable, especially after recharging it falls into some state where it only utters static noise. In this state it still plays music over the aux cable, but not any more over bluetooth.&lt;!-- more --&gt;
&lt;/p&gt;
&lt;p&gt;Apparently the issue is the aux port which has two contacts that should touch each other when there is no aux cable inserted. But, because of manufacture problems these two contacts don&amp;#8217;t touch on some device, even though there is no aux cable inserted. So: The jambox thinks there is an aux cable, but there is none. That&amp;#8217;s why it utters static noise&lt;/p&gt;
&lt;p&gt;
  So, because I have a device with such problems I needed to hard reset my jambox half a dozen. That&amp;#8217;s why I thought I finally write it down.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
    &lt;strong&gt;Soft reset&lt;/strong&gt;: Holding down the circle button (talk button) and plugging it into the charger and then releasing. You will see the red flash
  &lt;/li&gt;
  &lt;li&gt;Unpair / Pair again; being deleting it from every device, restarting all of them and pairing once more
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Hard reset&lt;/strong&gt;: Turn off bluetooth on all devices in reach, then turn on the jambox and press the circle button six times, when you see the light flash red, press the circle once more and hold it and it will go into pairing mode&lt;/li&gt;
  &lt;li&gt;Update the software to &amp;gt;=2.1 using &lt;a href="http://mytalk.jawbone.com"&gt;mytalk.jawbone.com&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Insert an &lt;strong&gt;aux cable&lt;/strong&gt; and removing it again (worked a few times for me)&lt;/li&gt;
  &lt;li&gt;Insert a small &lt;strong&gt;screw driver&lt;/strong&gt; (this is scary, more detailed instructions &lt;a href="http://forums.jawbone.com/t5/JAMBOX-Troubleshooting/jambox-static-and-airplay/m-p/14882/highlight/true#M748"&gt;here&lt;/a&gt;). This connects the two metal contacts which should touch each other to make the Jambox believe there is no AUX cable inserted&lt;/li&gt;
  &lt;li&gt;If the screw driver thing is working for you, you might consider putting a screw into the aux port: &lt;a href="http://i.imgur.com/udCI5.jpg"&gt;&lt;img src="http://i.imgur.com/udCI5.jpg" width="120" height="90"/&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;If nothing of the above works, you can &lt;a href="http://howto.pui.ch/post/37471161448/how-to-fix-jambox-static-noise-and-no-bluetooth"&gt;solder a bypass of the aux port&lt;/a&gt; (which is what I finally did)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;
  I don&amp;#8217;t recommend buying a Jambox to anyone, I completely agree with &lt;a href="http://www.amazon.com/review/R3GYH7DT8H8EKR/ref=cm_cr_pr_cmt?ie=UTF8&amp;amp;ASIN=B004E10KGU"&gt;this review on Amazon&lt;/a&gt;
&lt;/p&gt;</description><link>http://howto.pui.ch/post/37471160886</link><guid>http://howto.pui.ch/post/37471160886</guid><pubDate>Sat, 14 Jul 2012 13:26:00 -0400</pubDate><category>gadgets</category></item><item><title>keyboard shortcuts in iTerm2 on OS X</title><description>&lt;p&gt;&lt;span&gt;I love having my terminal completely on the server, so I can connect from everywhere and just resume with all my windows.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;That&amp;#8217;s why I always work on tmux and my iTerm just has one tab.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;That&amp;#8217;s why I remapped e.g. cmd-t to &amp;#8220;new tmux tab&amp;#8221; and cmd-w to &amp;#8220;close tmux tab&amp;#8221;.&lt;!-- more --&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;To achieve this, in tmux&amp;#8217; preferences in keys you need to add global shortcut keys. I&amp;#8217;m using ctrl-z as prefix, if you use ctrl-a use 0x01 instead. These are the combinations for ctrl-z (L&lt;/span&gt;&lt;span&gt;ist items are: Key combinations - Hex Codes - Comment):&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;span&gt;⌘0 - &lt;em&gt;0x1a 0x22&lt;/em&gt; - switch to window 0. Other window suffixes (replace 22 by that): 1=31,2=32,3=33,4=34,5=35,6=36,7=37,8=38,9=39&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;⌘r - &lt;em&gt;0x1a 0x2c 0x08&amp;#160;0x08&amp;#160;0x08&amp;#160;0x08&amp;#160;0x08&lt;/em&gt; - rename current window (0x08 sends backspace)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;⌘t - &lt;em&gt;0x1a 0x63 - &lt;/em&gt;new &amp;#8220;tab&amp;#8221; (=new tmux window)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;⌘w - 0x04 - sends ctrl-d&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;⌥⌘← - 0x1a 0x1b 0x5b 0x44 - jump to plane to the left (ctrl-z &amp;#8221; or ctrl-z % to split windows into panes in tmux). Replace 0x44 by 0x41 (up), 0x42 (down), 0x43 (right)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;⌘↑ - 0x1a 0x5b - jump to tmux history&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;span&gt;Use &lt;/span&gt;&lt;code&gt;showkey --ascii&lt;/code&gt;&lt;span&gt; on the shell to inspect the hex keys of key strokes.&lt;/span&gt;&lt;/p&gt;</description><link>http://howto.pui.ch/post/37471160485</link><guid>http://howto.pui.ch/post/37471160485</guid><pubDate>Mon, 25 Jun 2012 09:46:00 -0400</pubDate><category>os x</category><category>bash</category></item><item><title>Python: easy way to show progress</title><description>&lt;p&gt;I use this quite often to indicate how long a loop takes:&lt;/p&gt;
&lt;pre&gt;for i, entry in enumerate(entries):
  # do something
  print "\r%s/%s" % (i, len(entries)),
  sys.stdout.flush()
&lt;/pre&gt;
&lt;p&gt;It shows&lt;br/&gt;1/13&lt;br/&gt;2/13&lt;br/&gt;&amp;#8230;&lt;br/&gt;on the same line (similar to a progress bar)&lt;/p&gt;</description><link>http://howto.pui.ch/post/37471159741</link><guid>http://howto.pui.ch/post/37471159741</guid><pubDate>Wed, 19 Jan 2011 06:53:00 -0500</pubDate><category>python</category></item><item><title>Python: display refreshing status (like top)</title><description>&lt;p&gt;In scripts I often want to display some status information (e.g. progress), this can be achieved with e.g.:&lt;/p&gt;
&lt;pre&gt;print "progress: %i %%\r" % i,
sys.stdout.flush()
&lt;/pre&gt;
&lt;p&gt;but this just works for one-liners. I wanted to have what &lt;code&gt;top&lt;/code&gt; or &lt;code&gt;less&lt;/code&gt; do: open a new &amp;#8220;window&amp;#8221; and being able to write &lt;strong&gt;everywhere&lt;/strong&gt; in the window, not just on the last line.&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;Found out that &lt;a href="http://docs.python.org/library/curses.html"&gt;curses&lt;/a&gt; does exactly that - but I didn&amp;#8217;t find a stripped-to-the-bare-necessities-example, so here you are:&lt;/p&gt;
&lt;pre&gt;import curses, time
from datetime import datetime
w = curses.initscr()
try:
  while True:
  w.erase()
  w.addstr("some status..\ncurrent time\n%s" % datetime.now())
  w.refresh()
  time.sleep(1)
finally:
  curses.endwin()
&lt;/pre&gt;</description><link>http://howto.pui.ch/post/37471159398</link><guid>http://howto.pui.ch/post/37471159398</guid><pubDate>Sun, 04 Apr 2010 18:24:00 -0400</pubDate><category>python</category></item><item><title>Python: Print list of dicts as ascii table</title><description>&lt;p&gt;Sometimes I want to print list of dicts as an ascii table, like this:&lt;/p&gt;
&lt;pre&gt;  | Programming Language | Language Type | Years of Experience |
  +----------------------+---------------+---------------------+
  | python               | script        |                    4 |
  | php                  | script        |                    5 |
  | java                 | compiled      |                   11 |
  | assember             | compiled      |                   15 |
&lt;/pre&gt;
&lt;p&gt;I searched on Google - but without luck.&lt;!-- more --&gt;&lt;br/&gt;&lt;br/&gt; That&amp;#8217;s what I came up with - it&amp;#8217;s not particularly nice but it does the job:&lt;/p&gt;
&lt;pre&gt;  def table_print(data, title_row):
    """
    data: list of dicts,
    title_row: e.g. [('name', 'Programming Language'), ('type', 'Language Type')]
    """
    max_widths = {}
    data_copy = [dict(title_row)] + list(data)
    for col in data_copy[0].keys():
      max_widths[col] = max([len(str(row[col])) for row in data_copy])
    cols_order = [tup[0] for tup in title_row]

    def custom_just(col, value):
      if type(value) == int:
        return str(value).rjust(max_widths[col])
      else:
        return value.ljust(max_widths[col])

    for row in data_copy:
      row_str = " | ".join([custom_just(col, row[col]) for col in cols_order])
      print "| %s |" % row_str
      if data_copy.index(row) == 0:
        underline = "-+-".join(['-' * max_widths[col] for col in cols_order])
        print '+-%s-+' % underline

  &lt;/pre&gt;
&lt;p&gt;Use it like that:&lt;/p&gt;
&lt;pre&gt;  data = [dict(name='python', type='script', years_experience=4),
    dict(name='php', type='script', years_experience=5),
    dict(name='java', type='compiled', years_experience=11),
    dict(name='assember', type='compiled', years_experience=15)
    ]
  titles = [('name', 'Programming Language'),
    ('type', 'Language Type'),
    ('years_experience', 'Years of Experience')]
  table_print(data, titles)
  &lt;/pre&gt;
&lt;p&gt;It will produce the table printed above. It&amp;#8217;s not fancy - the only &amp;#8216;smart&amp;#8217; thing it does is &lt;strong&gt;right-adjusting integers, strings are left-adjusted&lt;/strong&gt;.&lt;br/&gt;&lt;br/&gt; P.S. no, I don&amp;#8217;t have 15 years of experience of Assembler - I just know it since 15 years - it&amp;#8217;s one of the first programming languages I learned - and I even wrote a text editor with it - then I learned that&amp;#8217;s probably not the best language to write an editor :-)&lt;/p&gt;</description><link>http://howto.pui.ch/post/37471158914</link><guid>http://howto.pui.ch/post/37471158914</guid><pubDate>Sat, 27 Feb 2010 06:55:00 -0500</pubDate><category>python</category></item><item><title>dealing with "MySQL backend does not support timezone-aware datetimes"</title><description>&lt;p&gt;
      When &lt;a href="http://howto.pui.ch/post/37471158372/fetch-publicly-available-google-calendar-data-with"&gt;fetching events from an iCal feed and saving this into a database&lt;/a&gt; I got&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
    &lt;blockquote&gt;
      MySQL backend does not support timezone-aware datetimes
    &lt;/blockquote&gt;
    &lt;p&gt;&lt;!-- more --&gt;
      This did the trick for me: Install &lt;a href="http://pytz.sourceforge.net/"&gt;pytz&lt;/a&gt; (&lt;a href="http://sourceforge.net/projects/pytz/"&gt;download here&lt;/a&gt;)&lt;br/&gt;&lt;/p&gt;&lt;pre&gt;
import pytz
that_datetime_in_utc.astimezone(pytz.timezone('Europe/Zurich')).replace(tzinfo=None)
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Caution&lt;/strong&gt;: I don&amp;#8217;t really understand what I&amp;#8217;m writing here - it feels like those posters in PHP forums who explain &amp;#8216;how to &amp;#8230;&amp;#8217; and then trying to explain something they have no clue of, but well.. :-)&lt;/p&gt;</description><link>http://howto.pui.ch/post/37471158729</link><guid>http://howto.pui.ch/post/37471158729</guid><pubDate>Wed, 30 Dec 2009 18:27:00 -0500</pubDate><category>python</category></item><item><title>Fetch publicly available google calendar data with python</title><description>&lt;p&gt;
      I tried &lt;a href="http://code.google.com/apis/calendar/data/1.0/developers_guide_python.html"&gt;accessing the google data api with python&lt;/a&gt; - that api seems either overly complicated or just not suited for just grabbing events from a public google calendar.&lt;br/&gt;&lt;!-- more --&gt;
      &lt;br/&gt;
      This worked for me:&lt;br/&gt;&lt;/p&gt;
    &lt;ol&gt;&lt;li&gt;find out ical address (subscribe to the calendar, other calendars-&amp;gt;arrow down-&amp;gt;calendar settings)
      &lt;/li&gt;
      &lt;li&gt;install &lt;a href="http://codespeak.net/icalendar/"&gt;icalendar&lt;/a&gt;
      &lt;/li&gt;
    &lt;/ol&gt;&lt;p&gt;
      Then this is possible:
&lt;/p&gt;&lt;pre&gt;      
from icalendar import Calendar
import urllib
ics = urllib.urlopen('http://www.google.com/calendar/ical/fchppllvcaupb6fgguigobkfj4@group.calendar.google.com/public/basic.ics').read()
ical=Calendar.from_string(ics)
for vevent in ical.subcomponents:
 if vevent.name != "VEVENT":
  continue
 title = str(vevent.get('SUMMARY'))
 description = str(vevent.get('DESCRIPTION'))
 location = str(vevent.get('LOCATION'))
 start = vevent.get('DTSTART').dt      # a datetime
 end = vevent.get('DTEND').dt        # a datetime
&lt;/pre&gt;</description><link>http://howto.pui.ch/post/37471158372</link><guid>http://howto.pui.ch/post/37471158372</guid><pubDate>Tue, 29 Dec 2009 16:31:00 -0500</pubDate><category>python</category></item><item><title>Send javascript errors by mail</title><description>&lt;p&gt;
  I&amp;#8217;m running &lt;a href="http://extranet.icoc.ch"&gt;a Django-powered site for a closed user group&lt;/a&gt; and added a bit of JavaScript magic here and there (mainly &lt;a href="http://www.prototypejs.org/"&gt;Prototype&lt;/a&gt; and &lt;a href="http://codylindley.com/Javascript/219/finding-a-javascript-tool-tip-script"&gt;Tooltip&lt;/a&gt;).&lt;br/&gt;&lt;br/&gt;&lt;!-- more --&gt;
  Now Django sends me a mail whenever a 404 or 500 error occurs. But when one of my users encounters a JavaScript-Error, I&amp;#8217;m not informed. I thought anyone in the web has solved this problem but didn&amp;#8217;t find anything, so here&amp;#8217;s my take: Just send any error using Ajax (here: using &lt;a href="http://www.prototypejs.org/learn/introduction-to-ajax"&gt;Prototypes Ajax abstraction&lt;/a&gt;) to the server&lt;br/&gt;&lt;/p&gt;
&lt;pre&gt;
onerror = Extranet.mailError;
function mailError(msg, url, line) {
 var postBody = 'url=' + url + '&amp;amp;line=' + line + '&amp;amp;message=' + escape(msg) + '&amp;amp;useragent=' + escape(navigator.userAgent) + '&amp;amp;user=' + escape(user_name);
 var myAjax = new Ajax.Request('/api/jserror/', {method: 'post', postBody: postBody});
}
&lt;/pre&gt;
&lt;p&gt;
  &lt;code&gt;user_name&lt;/code&gt; is a JavaScript variable holding the Django username (so I know whom I can inform when the error is fixed).&lt;br/&gt;&lt;br/&gt;
  On the server side, I just send me mails containing the JavaScript error message, the username and the user agent:&lt;/p&gt;

&lt;pre&gt;
def jserror(request):
 from django.core.mail import mail_admins
 omit_messages = ['pointerobj is not defined', 'tipobj is not defined', 'ns6 is not defined', 'enabletip is not defined']
 if request.POST.get('message', '') not in omit_messages:
  message = """url: %s (%s)
%s
user-agent: %s
username: %s
""" % (request.POST.get('url', ''), request.POST.get('line', ''), request.POST.get('message', ''), request.POST.get('useragent', ''), request.POST.get('user', ''))
  mail_admins("javascript error", urldecode(message))
 return HttpResponse()
&lt;/pre&gt;
&lt;p&gt;  
  Yeah, that&amp;#8217;s all very trivial but I wonder what other solutions exist for this problem&amp;#8230;
&lt;/p&gt;</description><link>http://howto.pui.ch/post/37471157855</link><guid>http://howto.pui.ch/post/37471157855</guid><pubDate>Sat, 06 Oct 2007 09:33:00 -0400</pubDate><category>python</category><category>django</category><category>javascript</category></item><item><title>Django: Serve big files via fcgid</title><description>I&amp;#8217;ve got a &lt;a href="http://extranet.icoc.ch"&gt;django project&lt;/a&gt; running which requires you to login to access files.&lt;br/&gt;
That means that I have to serve the files via python, like this:&lt;br/&gt;&lt;pre&gt;
  @login_required
  def download(request, filename):
    # ... some code specific to my site ...
    response = HttpResponse(mimetype=postUpload.mimetype)
    response['Content-Disposition'] = "attachment; filename=" + original_filename
    response['Content-Length'] = os.path.getsize(filename_path)
    response.write(open(filename_path).read())
    return response
&lt;/pre&gt;
&lt;!-- more --&gt;
&lt;p&gt;
The problem: If the download of a file exceeded 5 minutes (big files and/or low
bandwidth) the download was canceled on the server side by a timeout. This Apache
configuration for mod_fcgid solved the problem (see &lt;a href="http://fastcgi.coremail.cn/doc.htm"&gt;mod_fcgid documentation for BusyTimeout&lt;/a&gt;)&lt;/p&gt;

&lt;pre&gt;
&amp;lt;IfModule mod_fcgid.c&amp;gt;
 BusyTimeout 1200
&amp;lt;/IfModule&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
The problem was that the apache module scanned every minute for processes that run for
more than BusyTimeout seconds. These processes are potentially in bad health (infinite
loop et al.) and have to be killed. Not so with my processes (since I know what I&amp;#8217;m
doing..). The setting of the busy timeout to 1200 seconds now lets my processes run for
a maximum of one hour.&lt;/p&gt;

&lt;p&gt;As this setting can&amp;#8217;t by overwritten in a htaccess file by default I needed to bug
&lt;a href="http://www.citrin.ch/"&gt;my web hosting provider&lt;/a&gt; with the request, which was
handled in 24 hours, so thanks for that one!&lt;/p&gt;
&lt;p&gt;PS: If you know of another way how to serve protected static files via a single sign on
(no HTTP basic auth), please let me know.&lt;/p&gt;</description><link>http://howto.pui.ch/post/37471157406</link><guid>http://howto.pui.ch/post/37471157406</guid><pubDate>Wed, 03 Oct 2007 04:14:00 -0400</pubDate><category>python</category><category>django</category></item><item><title>Python: Sort a list of dicts by dict-key</title><description>&lt;p&gt;I always forget that one and end up searching for half an hour:&lt;/p&gt;&lt;pre&gt;
  &amp;gt;&amp;gt;&amp;gt; l = [ dict(a=1,b=2,c=3),
  ... dict(a=2,b=2,c=2),
  ... dict(a=3,b=2,c=1)]
  &amp;gt;&amp;gt;&amp;gt; l.sort(key=operator.itemgetter('c'))
  &amp;gt;&amp;gt;&amp;gt; l
  [{'a': 3, 'c': 1, 'b': 2}, {'a': 2, 'c': 2, 'b': 2}, {'a': 1, 'c': 3, 'b': 2}]
  &amp;gt;&amp;gt;&amp;gt; l.sort(key=operator.itemgetter('a'))
  &amp;gt;&amp;gt;&amp;gt; l
  [{'a': 1, 'c': 3, 'b': 2}, {'a': 2, 'c': 2, 'b': 2}, {'a': 3, 'c': 1, 'b': 2}]
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: This is a more elegant way to do the same:&lt;/p&gt;

&lt;pre&gt;
&amp;gt;&amp;gt;&amp;gt; l = [ dict(a=1,b=2,c=3),
... dict(a=2,b=2,c=2),
... dict(a=3,b=2,c=1)]
&amp;gt;&amp;gt;&amp;gt; sorted(l, key=lambda k: k['c'])
[{'a': 3, 'b': 2, 'c': 1}, {'a': 2, 'b': 2, 'c': 2}, {'a': 1, 'b': 2, 'c': 3}]
&lt;/pre&gt;</description><link>http://howto.pui.ch/post/37471157116</link><guid>http://howto.pui.ch/post/37471157116</guid><pubDate>Mon, 23 Jul 2007 10:52:00 -0400</pubDate><category>python</category></item><item><title>Python: Find out cpu time of a certain process</title><description>&lt;p&gt;
  To find out how many percentage a certain process uses the cpu:
&lt;/p&gt;
&lt;!-- more --&gt;
&lt;pre&gt;
  import os, time

  # find out the pid by username.
  # "-o pid h" omits the header and just prints the pid
  pid = os.popen('ps -U my_user_name -o pid h').read().strip()

  # 14th column is utime, 15th column is stime:
  # The time the process has been scheduled in user/kernel mode
  # The time value is in jiffies. One jiffie is appox 1/100 second
  # see man proc for more info
  stat = os.popen('cat /proc/%s/stat' % pid).read().strip()
  cpu_time1=int(stat.split()[14]) + int(stat.split()[15])
  time1=time.time()

  time.sleep(1)
  stat = os.popen('cat /proc/%s/stat' % pid).read().strip()
  cpu_time2=int(stat.split()[14]) + int(stat.split()[15])
  time2=time.time()

  print str(float(cpu_time2 - cpu_time1) / (time2 - time1)) + "%"
&lt;/pre&gt;
&lt;p&gt;
  I don&amp;#8217;t know though if the number is accurate.&lt;br/&gt;
  What is &amp;#8220;cpu time&amp;#8221; anyway? It&amp;#8217;s the time the process is running (using the cpu for 100%) divided by the time the process is laid asleep by the scheduler.&lt;br/&gt;
  Then, &lt;a href="http://www.ecos.sourceware.org/ml/systemtap/2005-q4/msg00185.html"&gt;jiffies seem to be not a safe number&lt;/a&gt; for time measurements.&lt;br/&gt;
  But for relative measurements it should do the trick.
&lt;/p&gt;</description><link>http://howto.pui.ch/post/37471156554</link><guid>http://howto.pui.ch/post/37471156554</guid><pubDate>Fri, 08 Jun 2007 06:52:00 -0400</pubDate><category>python</category></item><item><title>add bandwidth to a file download in python</title><description>&lt;p&gt;
      Another short code snippet I came up when writing the &lt;a href="http://code.pui.ch/2007/02/18/turn-demoscene-modules-into-mp3s/"&gt;module download script&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;
      The following class keeps a download under a certain ratio and prints live download stats (KB/s).&lt;br/&gt;
      &lt;!-- more --&gt;&lt;/p&gt;
&lt;pre&gt;
  class BandwidthFile:
    """
    limits the file download to a certain amount of bytes per second and prints download stats
    """
    def __init__(self, filename, filesize, bytes_per_second = 20000, mode = "wb"):
      self.fp = open(filename, "wb")
      self.bytecounter = 0
      self.started = datetime.datetime.now()
      self.bytes_per_second = bytes_per_second
      self.filesize = filesize
      self.filename = filename

    def __del__(self):
      self.fp.close()

    def write(self, bytestring):
      self.bytecounter += len(bytestring)
      seconds_since_started = (datetime.datetime.now() - self.started).seconds + 1
      while (self.bytecounter / seconds_since_started)&amp;gt; self.bytes_per_second:
        seconds_since_started = (datetime.datetime.now() - self.started).seconds + 1
        time.sleep(0.1)
      self.fp.write(bytestring)
      sys.stdout.write("\rdownloading %s (%i/%i KB, %i KB/s)" % (self.filename, (self.bytecounter / 1024), (int(self.filesize) / 1024), (self.bytecounter /seconds_since_started / 1024)))
      sys.stdout.flush()
&lt;/pre&gt;
&lt;p&gt;
      To use the class with ftp:
&lt;/p&gt;

&lt;pre&gt;
  from ftplib import FTP
  ftp = FTP("ftp.modland.com")
  filesize = &lt;a href="http://ftp.size"&gt;ftp.size&lt;/a&gt;(remote_filename)
  f = BandwidthFile(local_filename, ftp_filesize)
  &lt;a href="http://ftp.retrbinary"&gt;ftp.retrbinary&lt;/a&gt;('RETR '+remote_filename, f.write)
&lt;/pre&gt;
&lt;p&gt;
      The status line looks like this:&lt;br/&gt;&lt;/p&gt;
&lt;pre&gt;
  downloading /home/phred/modules/Skaven/beyond the network.it (95/4411 KB, 19 KB/s)
&lt;/pre&gt;
    &lt;p&gt;
      &lt;br/&gt;&lt;br/&gt;
      If you have suggestions how to enhance the code snippet feel free to leave a comment!
    &lt;/p&gt;</description><link>http://howto.pui.ch/post/37471156141</link><guid>http://howto.pui.ch/post/37471156141</guid><pubDate>Sat, 24 Feb 2007 21:51:00 -0500</pubDate><category>python</category></item><item><title>set timeout for a shell command in python</title><description>&lt;p&gt;
      I wanted to run a shell command in python without knowing if the shell command is going to exit within reasonable time (&lt;a href="http://adplug.sourceforge.net/"&gt;adplay&lt;/a&gt; that was, sometimes it simply hangs).&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href="http://www.python.net/crew/hooft/"&gt;the &amp;#8220;task&amp;#8221; module of Rob Hooft&lt;/a&gt; seems to solve this exact problem. At the time I wrote this, the python.net website was down. I leave my solution here just for archive purpose.&lt;br/&gt;&lt;br/&gt;&lt;!-- more --&gt;&lt;/p&gt;
&lt;pre class="linenum"&gt;
  def timeout_command(command, timeout):
    """call shell-command and either return its output or kill it
    if it doesn't normally exit within timeout seconds and return None"""
    import subprocess, datetime, os, time, signal
    start = datetime.datetime.now()
    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    while process.poll() is None:
      time.sleep(0.1)
      now = datetime.datetime.now()
      if (now - start).seconds&amp;gt; timeout:
        os.kill(process.pid, signal.SIGKILL)
        os.waitpid(-1, os.WNOHANG)
        return None
    return process.stdout.read()
&lt;/pre&gt;
&lt;p&gt;Note especially lines 6, 11 and 12.&lt;br/&gt;Usage:&lt;/p&gt;
&lt;pre&gt;
  &amp;gt;&amp;gt;&amp;gt; output = timeout_command(["sleep", "10"], 2)
  None
  &amp;gt;&amp;gt;&amp;gt; output = timeout_command(["sleep", "1"], 2)
&lt;/pre&gt;
&lt;p&gt;The process can be killed when it has run for too long (the &lt;code&gt;os.waitpid&lt;/code&gt; waits for the kill to end and avoids defunct-processes) and furthermore the Popen&amp;#8217;ed process&amp;#8217; printed is caught and returned if it doesn&amp;#8217;t timeout. However, &lt;code&gt;subprocess.Popen&lt;/code&gt; is called with a list as argument. That means, that the command isn&amp;#8217;t passed to a shell and furthermore you can just call one command with options, nothing more.&lt;/p&gt;</description><link>http://howto.pui.ch/post/37471155682</link><guid>http://howto.pui.ch/post/37471155682</guid><pubDate>Sun, 18 Feb 2007 19:04:00 -0500</pubDate><category>python</category></item></channel></rss>
