[Python-Dev] Problems with GeneratorExit deriving from Exception

2007-12-01 Thread Chad Austin
Hello Python-Dev,

Here at IMVU, we love Python 2.5's generators-as-coroutines.  That feature has
let us succinctly express algorithms that intermix asynchronous network requests
and UI operations without writing complicated state machines, and, perhaps most
importantly, get high-quality unit tests around these algorithms.

However, we've been having a problem with the way GeneratorExit interacts with
our coroutine system.  Let's take a bit of simplified example code from our 
system:

@task
def pollForChatInvites(chatGateway, userId):
while True:
try:
# Network call.
result = yield 
chatGateway.checkForInvite({'userId': userId})
except Exception:  # An XML-RPC call can fail for many 
reasons.
result = None
# ... handle result here
yield Sleep(10)

If a task (coroutine) is cancelled while it's waiting for the result from
checkForInvite, a GeneratorExit will be raised from that point in the generator,
which will be caught and ignored by the "except Exception:" clause, causing a
RuntimeError to be raised from whoever tried to close the generator.  Moreover,
any finally: clauses or with-statement contexts don't run.

We have also run into problems where a task tries to "return" (yield Return())
from within a try: except Exception: block.  Since returning from a coroutine is
roughly equivalent to "raise GeneratorExit", the exception can be caught and
ignored, with the same consequences as above.

This problem could be solved in several ways:

1) Make GeneratorExit derive from BaseException, just like SystemExit.

2) Add "except GeneratorExit: raise" to every usage of except Exception: in 
tasks.

3) Change the semantics of except clauses so that you can use any container as
an exception filter.  You could have a custom exception filter object that would
catch any Exception-derived exception except for GeneratorExit.  Then we'd have
to teach the team to use "except ImvuExceptionFilter:" rather than "except
Exception:".

I prefer option #1, because it matches SystemExit and I haven't ever seen a case
where I wanted to catch GeneratorExit.  When a generator is closed, I just want
finally: clauses to run, like a normal return statement would.  In fact, we have
already implemented option #1 locally, but would like it to be standard.

Option #2 would add needless noise throughout the system,

You could argue that it's bad style to catch Exception, but there are many
situations where that's exactly what I want.  I don't actually care _how_ the
xml-rpc call failed, just that the error is logged and the call is retried
later.  Same with loading caches from disk.

Proposals for changing GeneratorExit to be a BaseException have come up on this
list in the past [1] [2], but were rejected as being too "theoretical".  A
significant portion of the IMVU client is now specified with coroutines, so I
hope to resume this conversation.

Thoughts?

Chad

[1] http://mail.python.org/pipermail/python-dev/2006-March/062654.html
[2] http://mail.python.org/pipermail/python-dev/2006-March/062825.html

-- 
http://imvu.com/technology


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Problems with GeneratorExit deriving from Exception

2007-12-01 Thread Chad Austin
Guido van Rossum wrote:
> On Dec 1, 2007 2:38 PM, Chad Austin <[EMAIL PROTECTED]> wrote:
>> This problem could be solved in several ways:
>>
>> 1) Make GeneratorExit derive from BaseException, just like SystemExit.
> 
> Well argued. I suggest to go for option (1) -- make GeneratorExit
> inherit from BaseException. We can do this starting 2.6. Feel free to
> upload a patch to bugs.python.org.

Great!  Patch is uploaded at http://bugs.python.org/issue1537

The patch changes the definition of GeneratorExit so that it extends 
BaseException, adds a generator test, updates exception_hierarchy.txt, and 
updates the exceptions page in the documentation.  This is my first patch to 
Python -- did I miss anything?

Thanks,
Chad
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Problems with GeneratorExit deriving from Exception

2007-12-02 Thread Chad Austin
Hi Antoine,

Antoine Pitrou wrote:
> Hi,
> 
> (I was asked to forward this from the bug tracker)
> 
>> We have also run into problems where a task tries to "return" (yield 
>> Return())
>> from within a try: except Exception: block.  Since returning from a 
>> coroutine is
>> roughly equivalent to "raise GeneratorExit", the exception can be caught and
>> ignored, with the same consequences as above.
> 
> I may be missing something but why don't you just catch StandardError
> instead? If I believe Python 2.5's exception hierarchy it would catch
> anything under Exception except for GeneratorExit, StopIteration and the
> various Warnings.

If socket.error, xmlrpclib.Fault, httplib.HTTPException, etc. all extended 
StandardError, then we would probably be fine with that approach.  But I think 
the majority of exceptions, both in the standard library and our code, extend 
Exception directly.

> Also it seems to me that muting any Exception is bad practice since it
> can lead you to overlook errors in your code. It's better to catch a
> specific Exception subclass, like IOError (or XMLRPCError, or whatever
> it is called).

Yes, in general, it's better to catch specific errors, but sometimes it really 
is the case that it doesn't matter why the call failed, as long as your unit 
and 
acceptance tests verify that the code behaves as expected and you log any 
exceptions that do occur.  In fact, our logger remembers the last N error or 
exception log entries and automatically sends them back to our servers for 
analysis.  So think of it as protecting the application from intermittent 
failures rather than silently dropping exceptions.  :)

Chad
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com