Exploring Python
================
Simon Willison
Stack Overflow DevDays
Amsterdam 2 Nov 2009
------------------------------------
Python fundamentals
- Dynamic language
(not scripting, not weakly typed)
- General purpose
- Compiles to bytecode
- Significant whitespace
(get over it already!)
- 18 years old
- Multiple implementations
CPython, Jython, IronPython, PyPy
- Open source
In an interactive prompt:
$ python
>>> print "hello world"
'hello world'
>>> import urllib
>>> u = urllib.urlopen("http://stackoverflow.carsonified.com/")
>>> u.read()
...
>>> u.geturl()
...
>>> u.info()
...
>>> import this # the Zen of Python
The rest of the demos used iPython: http://ipython.scipy.org/
$ ipython # some of the below will throw errors, that's OK
>>> d = {'dog': 1, 'cat': 123, ('foo', 'bar'): {'moo': 'foo'}}
>>> t = (1, 2, 45, 12, 'dog')
>>> l = ['dog', 'cat', 12, ('a', 'b')]
>>> s = set(['a', 'b', 'c'])
>>> l
>>> t
>>> del l[0]
>>> l
>>> del t[0]
>>> l[0]
>>> l[1]
>>> len(l)
>>> for item in l:
... print item
>>> d['cat']
>>> d[('foo', 'bar')]
>>> d[[234, 234]] = 12
>>> s
>>> 'a' in s
>>> 'oenuth' in s
------------------------------------
Next I talked about the BNP mapping project:
www.guardian.co.uk/politics/2009/oct/20/bnp-membership-list-wikileaks
www.guardian.co.uk/politics/interactive/2009/oct/19/bnp-membership-uk-map
It turns out these are called http://en.wikipedia.org/wiki/Choropleth_map
Then I showed how to make a world-wide Choropleth using the Guardian's data
on numbers of endangered species (in particular mammals).
http://en.wikipedia.org/wiki/File:BlankMap-World6.svg was the source SVG map
www.guardian.co.uk/environment/datablog/2009/oct/23/endangered-species-red-list-data-review
http://spreadsheets.google.com/ccc?key=tYrEXu8zzrPw_b6C775X-iA
Or grab the CSV directly with this link:
http://spreadsheets.google.com/pub?key=tYrEXu8zzrPw_b6C775X-iA&output=csv
>>> import csv
>>> reader = csv.reader('endangered.csv')
>>> headers = reader.next()
>>> row = reader.next()
>>> zip(headers, row)
>>> dict(_)
>>> reader = csv.reader('endangered.csv')
>>> headers = reader.next()
>>> headers[1] = 'ISO'
>>> headers[2] = 'Mammals'
>>> rows = []
>>> for row in reader:
... rows.append(dict(zip(headers, row)))
>>> mammals = [
... (r['ISO'], int(r['Mammals']))
... for r in rows
... ]
>>> mammals.sort(key = lambda p: p[1])
In colourer.py:
class Colourer(object):
def __init__(self, min_col, max_col):
self.min_col = min_col
self.max_col = max_col
def colour(self, ratio):
return (
self.min_col[0] + ratio * (
self.max_col[0] - self.min_col[0]
),
self.min_col[1] + ratio * (
self.max_col[1] - self.min_col[1]
),
self.min_col[2] + ratio * (
self.max_col[2] - self.min_col[2]
),
)
>>> c = colourer.Colourer((255, 255, 255), (255, 0, 0))
>>> from xml.etree import ElementTree
>>> et = ElementTree.parse('BlankMap-World6.svg')
>>> et.getroot()
>>> et.getroot().find('./{http://www.w3.org/2000/svg}style')
>>> style = _
>>> print style.text
>>> def tohex(rgb):
... return '%02x%02x%02x' % rgb
>>> template = '.%s { fill: #%s; }'
>>> css = []
>>> for iso, value in mammals:
... if not iso:
... continue
... rgb = c.colour(value / 183.0)
... css.append(template % (iso.lower(), tohex(rgb)))
>>> rules = '\n'.join(css)
>>> style.text += rules
>>> et.write('output.svg')
>>> !open -a Firefox output.svg
The USA and Alaska showed up in grey due to an issue in the SVG file - I fixed
this by knocking out the style rule using "Inspect Element" in Firebug.
Half way through the above I digressed to talk about list comprehensions:
numbers = [1, 3 ,4]
doubles = [i * 2 for i in numbers]
odds = [i for i in numbers if i % 2 == 1]
[transform for item in iterable]
[transform for item in iterable if condition]
------------------------------------
Next I talked about PyPI, easy_install and virtualenv:
http://pypi.python.org/
http://peak.telecommunity.com/DevCenter/setuptools
http://pypi.python.org/pypi/virtualenv
I didn't mention it in the talk, but I would strongly recommend looking in to
pip as an alternative to the easy_install command:
http://pypi.python.org/pypi/pip
------------------------------------
The next example was a screen scraper for producing iCal files from the
conference website:
http://stackoverflow.carsonified.com/events/amsterdam/
The demo failed because I installed the wrong version of the library. I should
have used the latest version from http://codespeak.net/icalendar/
The code also used BeautifulSoup:
http://www.crummy.com/software/BeautifulSoup/
Here's the final code:
from BeautifulSoup import BeautifulSoup as Soup
import urllib
from dateutil import parser
import icalendar
URL = 'http://stackoverflow.carsonified.com/events/amsterdam/'
def scrape_ical(url):
soup = Soup(urllib.urlopen(url))
trs = soup.findAll('tr')
day = trs[0].findAll('th')[1].contents[0] + ' '
trs = trs[1:]
cal = icalendar.Calendar()
for tr in trs:
time_td = tr.findAll('td')[0]
summary_td = tr.findAll('td')[1]
start, end = time_td.contents[0].split(' - ')
summary = ''.join(summary_td.findAll(text=True))
event = icalendar.Event()
event.add('summary', summary)
event.add('dtstart', parser.parse(day + start))
event.add('dtend', parser.parse(day + end))
cal.add_component(event)
return cal
print scrape_ical(URL).as_string()
------------------------------------
Next I introduced Django:
http://www.djangoproject.com/
I demonstrated a Django implementation of the Stack Overflow DevDays site -
the code is available here: http://github.com/simonw/devdays/
------------------------------------
Advanced Topics
- Generators
infinite iterators by pausing and resuming
a function
- Metaclasses
A kind of constructor-for-classes - modify
how a class itself is constructed at runtime
- Coroutines
Building microthreads on top of generators
I strongly recommend the David Beazley tutorials:
http://www.dabeaz.com/generators-uk/index.html
http://www.dabeaz.com/coroutines/index.html
------------------------------------
The Future of Python
http://www.python.org/download/releases/3.1.1/
http://mail.python.org/pipermail/python-ideas/2009-October/006305.html
http://code.google.com/p/unladen-swallow/wiki/ProjectPlan
------------------------------------
Further reading
- Official Python Tutorial
http://docs.python.org/tutorial/index.html
- Dive Into Python
http://diveintopython.org/
- Dive Into Python 3
http://diveintopython3.org/
- http://simonwillison.net/tags/python/