Follow us on Twitter
Latest Tweet: New blog post on raw roles allowing arbitrary html in docutils < 0.6 http://blog.projectfondue.com/2010/7/27/security-raw-roles-in-docutils
L'Alpiniste

The blog of the Project Fondue Team

Python script for Text Link Ads

written by Ed Eliot, on 01 October, 2009 at 18:31

We've been using Text Link Ads (TLA) on some of our sites for a while now. It's a great service which allows publishers to sell sponsored links on their sites and has helped us pay our hosting bills to date. Once signed up you include sponsored links on your site via a server side script which they provide. They provide a number of different solutions - for common blogging platforms including Wordpress and Movable Type as well as straight PHP. Unfortunately they don't provide a solution for use with any other language so our use of Python restricted our use of the service.

To counter this I've written a simple Python script which replicates the functionality of their PHP script. It should be pretty solid and we've been using it on one of our sites for a while but, as this is the first bit of proper Python I've written, please go easy on me if you spot mistakes!

Usage

The script is pretty easy to use. Start by including the library.

import tla

The quickest way to test out the library is probably with the python command line interpreter. This will allow you to introspect its properties and methods with out initially worrying about how to make it sit alongside your own code.

Next create an instance of the TLA class passing the inventory code that was supplied to you by TLA.

tla = TextLinkAds('ENTER_TLA_INVENTORY_KEY_HERE')

The class has methods to supply the raw data or that same data formatted as an HTML unordered list.

data = tla.get_data()

print tla.get_html()

If you're using a templating engine such as jinja2 you'll probably need to make sure you mark the TLA output as "safe" to prevent to the engine from escaping the HTML tags returned.

Requirements

The script uses a couple of external libraries - httplib2 and memcache - httplib2 is required but memcache is optional and is, by default, disabled.

You can install both libraries with the following:

sudo easy_install python-memcached httplib2

The script also write temporary files to a directory specified within the script (by default /tmp). You'll need to make sure that it has permissions to write to this directory or change it to one it can write to.

Unit Tests

Stuart's written a number of unit tests for the library. Test coverage currently stands at around 70% which is pretty good. We'll obviously be looking to expand this coverage in due course.

Learning Python

Being new to Python, I learned quite a lot whilst writing the script. Stuart and Cyril provided plenty of suggestions which resulted in a number of rewrites. Much of this feedback was gathered via a lengthy code review, managed with Google's excellent code review tool - rietveld.

Here's a few nuggets of information you might find useful, if like me, you're just starting out.

  • httplib2 is much better than urllib2. It does far more out of box resulting in shorter, cleaner code.
  • Python provides excellent facilities for logging information - be it to a text file, by email or over HTTP. I found it a little confusing initially but perseverance definitely pays off. The Python docs have detailed information about what's possible and of course my script demonstrates relatively simple but effective usage.
  • Python uses Exceptions for every type of error. This may seem a little strange if you're used to PHPs rather hectic approach to handling errors. You'll need to get used to using try..except blocks everywhere in Python. Also, be careful to be explicit about what errors your catching. Naked excepts (those that catch every conceivable error) make it harder to track down problems later.
  • Building up a string by appending to a list which you later join is a common idiom in Python. As strings are immutable, concatenation results in a copy of the string being created every time.
  • Python supports calling functions and methods with named parameters as well as **kwargs - a dictionary from which named function parameters can be retrieved without the need for them to form part of the actual function definition. I wish PHP supported similar functionality.

Leave a Reply: