Archive for Python

Debugging Python with PDB

I suck at using debuggers, largely because I don’t launch them often enough.

Fortunately, this year’s PyCon had a great talk from Chris McDonough on how to get started with Python’s debugger, PDB. The friendly people at Stockholm’s Python meet-up suggested it.

I made notes while watching, to remove excuses from future me on launching pdb.

Where you want to have the debugger start, add the following code:

import pdb; pdb.set_trace()

This drops you into a PDB prompt. This is more helpful than putting in yet more
print statements.

Some helpful commands once you’re in:

  • l - list code
  • args - arguments to current function
  • p <var> - print a var
  • pp <var> - pretty print a var
  • n - next
  • s - step
  • w - where (stack trace for current position)
  • h - help

While in PDB, you can evaluate python code. The evaluated code won’t impact the running program.

For a bonus trick if you’re using Emacs, try out pdb track mode. Launch your python process to be debugged in an emacs shell (M-x shell). Stepping through the code in pdb will track with a source code buffer.

This worked out of the box with my emacs config. Your milage may vary.

I may actually start to enjoy debugging now!

Unit testing in Python with folder watching

Unit testing is good. Running unit tests manually is annoying.

Rspec has a great addition in autospec, which automatically re-runs specs that are changed or have the associated code changed. This model of working has a long history in the ruby community, with autotest.

I wanted a similar thing for python/nose, but hadn’t had much luck.

The solution is py.test, with some plugins added.

This was suggested to me at the Stockholm Python user group, and I am very grateful. My testing life is now much simpler.

To get started, try something like:

$ sudo pip install pytest pytest-xdist pytest-cov

The simple way to get started is to watch your tests folder:

py.test -f test/

Now as you change files, the relevant tests will automatically be re-run. Perfect to display on that second monitor.

As I was working on some legacy code, I was looking to improve the test coverage, so wanted to see how that was going with pytest-cov:

py.test -f --cov package.name test/

Adding the package.name for your main package means you won’t generate coverage for libraries you are using. Makes the output simpler.

Still not quite happy, it wasn’t showing me which lines I needed coverage on. No problem:

py.test -f --cov package.name --cov-report term-missing test/

For comparison, here is how to get similar results from nose, but without watch support:

nosetests test/
nosetests --with-coverage --cover-erase --cover-package=package.name test/

One hurdle I had with py.test was working with Twisted based test-cases. You need to ensure that you use a version of py.test later than 2.0. Debian squeeze does not package this by default, so use pip to install.

The annoyance is if you change the code so it doesn’t terminate. This still needs a context switch to kill off the tests and re-run. Keeps me focused on getting it right the first time.

pytest-xdist includes lots of really cool options, such as distribution of tests across multiple cores, versions, hosts and platforms.

I’ve since discovered this comprehensive summary of the options available. I’m happy I found this after selecting py.test, or I’d still be stuck in evaluation mode rather than writing code.

Update: check out sniffer if you want a more generic watcher framework.

My First WebApp

There are lots of technologies that I have been investigating recently, with the intent of building something useful. However, it’s hard to figure out if my plan makes sense without trying. So I am going to build a very simple application.

The specification looks like:

The application shall allow the user to send email notes to themselves

I often email short notes to myself as reminders or to capture short pieces of information. The number of steps involved in doing this is too many. I have to address the email, set a subject, navigate one of many email clients and then send. I want to IM myself and have it turn up as email.

My design for building this is a little bit more complex than it really needs to be. This is because the application is an excuse to try building a platform.

There are four pieces:

  1. Taskbar applet to send mail
  2. Web application to send mail
  3. Web service to receieve send mail request
  4. Application service to send mail

The task bar applet is the easy part (see QSystemTrayIcon). That will be built, initially for Windows, using Qt. If I’m enthusiastic, it may support RTF and HTML email as well as unicode text.

The web application, likely to be built last, will use django. I’m considering Ruby on Rails, but given I already know python and django provides sufficient functionality, it is my likely choice.

The web service will be built using the same web framework as the web application. I am trying to reduce the number of technologies a little bit.

The aims of the web service:

  • Provide a publically accessible API.
  • To allow for a flexible URL mapping scheme
  • To provide a REST style API.
  • To easily provide different data formats (XML, JSON).

The application service will be built using Haskell. It will be kept as an internal process. It will likely be built using a web service as well, but using JSON as the transport. I am choosing Haskell mainly to explore options.

After my recent foray into Lisp, I am confident I could build the application service using Lisp, but would prefer to use Haskell. This is partially to avoid paying license fees to Allegro, but mostly as I prefer having the type system of Haskell available. The architecture will allow me to swap back-ends if needed.

That is the plan. Progress and learnings should trickle in over the coming months.

Note: This is an exercise in playing with technology. There is no plan for providing this as a production level service.

Elementary Bluetooth using PyObjC

Bluetooth connectivity to devices is supported on Mac OS X using Cocoa APIs, so is possible to access from Python. Bluetooth itself opens up a large body of knowledge that I am only starting to investigate.

This article outlines some basics for using Bluetooth in Python.

Bluetooth access is achieved through two frameworks, IOBluetooth and IOBluetoothUI. Neither of these are included in PyObjC by default, so a basic wrapper class makes life easier. (see the PyObjC docs)

Add the following to IOBluetooth.py:


import objc as _objc

_objc.loadBundle('IOBluetooth', globals(),
  bundle_path=u'/System/Library/Frameworks/IOBluetooth.framework')

The loadBundle pattern is very useful, and allows the classes from any Objective C framework to be loaded into the PyObjC bridge. By putting it into a separate Python module, usage becomes less painful.

For example, the most recent device is:


>>> from IOBluetooth import *
>>> devs = IOBluetoothDevice.recentDevices_(1)
>>> devs[0].getNameOrAddress()
u'gmwils 6600'
>>> devs[0].isConnected()
1
>>>

In this case, my Nokia 6600 is still connected in AddressBook.

To create a new connection to a device, Apple provides access to their user interface for Bluetooth management. It is strongly recommended that these controls are used to provide consistency for the user and detailed error handling.

For example, selecting a service from a device with a dialog:


>>> from IOBluetoothUI import *
>>> browser = IOBluetoothServiceBrowserController.serviceBrowserController_(0)
>>> browser.runModal()
-1000
>>> results = browser.getResults()
>>> results[0].getServiceName()
u'Bluetooth Serial Port'
>>>

Note: you will need a IOBluetoothUI wrapper, similar to the IOBluetooth wrapper from earlier.

Useful documentation links:

Birthday Notes

Birthday Notes is an application with two purposes. On one hand it provides an easy way to keep track of people’s birthdays on Mac OS X. The other role it plays is to learn Cocoa programming using Python, Cocoa and PyObjC.

Why bother with yet another birthday tracking tool? Quite simply, most were too difficult to get the information that I wanted. The main aim of Birthday Notes is to provide a list of upcoming birthdays with relevant information.

For example, I rarely think of people’s birthdays in terms of their birth date (eg 1977-08-04). My brain is wired so that I remember that my birthday is on the 4th of August and that I’m currently 28 and turning 29 on my next birthday. Rather than show the birth date, Birthday Notes shows the birthday and the person’s age they turn on that day.

Birthday Notes features integration to Apple’s existing applications for storing data. This means that iSync support comes for free. The current focus is on a maintenance and reporting tool, so you can edit a person’s birthday from within Birthday Notes, but not create or delete. For additional actions, simply double click on the person’s name - they will be revealed in AddressBook.

I like to know some trivia about people’s birthdays, so Birthday Notes includes a bit of useless astrological information.

Birthday Notes is available for download. Requires OS X 10.4 or greater.

Any thoughts, suggestions, bugs or feedback should be sent to gmwils AT pseudofish.com, or posted in comments on this post.

For those interested in the code, it is available under a GPL license. To compile, Python 2.4, a recent build of PyObjC, and icalendar are needed.

Finally, my thanks to those who have been helping with alpha testing. This release marks the start of a public beta.