Recoverable Exceptions in Python Author:Michael Hudson Email:[email protected] Apologies for the very simple slides, I had tool problems, and ran out of time to try to fix them. This was largely because I kept changing my mind about what I wanted to say, and then how I wanted to say it...

What Do I Mean By A Recoverable Exception? Simply, an exception where it's possible to choose between various ways of dealing with the problem, including carrying on from the point where the problem was found and returning the error to calling code (as in Python). [CL demo]

Why Would We Want This? It's hard to really give a good answer to this. Error handling is a 'programming in the large' topic, not suited to simple demos in conference presentations. Part of the reason for this is that error handling is largely about protocol, and you don't really need protocol if you've written all the code involved (more on this later).

How Do We Do This? Think about how exception handling works in Python today: control is transferred to different code after unwinding the stack. To allow resumption after the error, we must transfer control to different code without unwinding the stack. This is just a function call.

How Might We Use This? Instead of: def divide(a, b): if b == 0: raise ZeroDivisionError() else: return a / b we might write: def divide(a, b): if b == 0: return handle(ZeroDivisionError()) else: return a / b handle can raise the error or return some "infinite" value as it sees fit.

A Sidestep: zope.event Part of Zope 3, the zope.event module allows you to tell interested but unknown to you code about situations you've encountered: def divide(a, b): if b == 0: zope.event.notify("dividing by zero") return HUGE_VAL else: return a / b It isn't an error handling system because it's only a notification: it's not expected that the event handlers will try to influence the course taken by the notifying code.

The Entire Code Of zope.event subscribers = [] def notify(event): for subscriber in subscribers: subscriber(event) Pretty simple huh?

So What's The Point? Why write zope.event if it's so simple? It's about protocol again: You or I could write zope.event at the drop of a hat, but for it to be useful, the code doing the notifying and the code doing the noticing have to use the same mechanism. zope.event is designed to impose the minimum amount of policy consistent with this goal (zope.app.event does something complicated with interfaces).

Another Sidestep: PEP 343 Exception handlers in Python today have what is called "dynamic extent"; they are active for a period of time determined by where control is in a program. If we are to implement an error handling system supporting system in Python, we want the same property and PEP 343 lets us do this. The system in a few slides time will let you write: with handler(a_handler): ... handler active here ....

More about PEP 343 Roughly speaking, part of PEP 343 proposes that: with expr as var: ... code ... becomes: hidden_var = expr var = hidden_var.__enter__() try: ... code ... finally: var.__exit__() (ignoring some stuff about exceptions).

On With The Code It was a bit of a stretch to fit it onto slides, so... [Python demo]

Restarts Even harder to fit examples of onto one side, experience in the common lisp community shows that there is value in adding another abstraction to the mix: restarts. A restart is, essentially a means of continuing. Code can arrange for restarts to be available, and a handler can choose among them. [Demo This]

So ... what? Just after I realised that restartable exceptions were really easy to implement, I'd originally intended to develop a fancy, amazing restartable exception system and show it off now. This didn't last very long; code written today that raises an exception doesn't expect control to be coming back and would break mightily if it did. What I'd like you to take away from this talk is the idea that when something goes wrong and you don't know what to do, don't just give up, maybe you can ask someone else what to do.

More Conclusions As to whether core Python would benefit from this approach, I find that really hard to say. As mentioned above, there should be at most one restartable exception implementation so there would be some advantage to bundling it with Python. Also, it would be nice if the Python core allowed continuation after some errors (NameErrors, anyone?), though lacking the ability to fix code while it's executing makes this less useful. Anyway, I hope this talk was interesting!

Credits and References I should certainly credit two of Kent Pitman's papers: * "Condition Handling in the Lisp Language Family" * "Exceptional Situations In Lisp" available on the web at: http://www.nhplace.com/kent/Papers/index.html I also read various things about error handling in Smalltalk, but ran out of time to research it properly (or talk about them). Steve Alexander pointed out zope.event to me.

Questions?