On Thu, Feb 6, 2014 at 12:09 PM, Yury Selivanov <yselivanov...@gmail.com>wrote:

>
> On 2/6/2014, 1:24 PM, Guido van Rossum wrote:
>
>> On Thu, Feb 6, 2014 at 8:53 AM, Yury Selivanov <yselivanov...@gmail.com>
>> wrote:
>>
>>  As discussed with Guido in issue #80
>>> (https://code.google.com/p/tulip/issues/detail?id=80),
>>> I'm proposing a strawman design for having a user definable event loop
>>> handler for unhandled exceptions.
>>>
>>> Two new API points:
>>>
>>>    - "loop.set_exception_handler(callback)"
>>>      Sets 'callback' as a new unhandled error handler for the event loop
>>>      'loop'. The signature of callback should be '(loop, exception,
>>> context)'
>>>      where: 'loop' parameter is the current event loop running;
>>> 'exception'
>>>      is the unhandled exception object; 'context' is a string (str),
>>>      that will be the basic context information, like
>>>      "unhandled exception in add_reader callback" (the kind of
>>> information
>>>      that usually goes to the log title).
>>>
>>>  I'd rename the context arg to 'message', then you don't have to explain
>> what it is. :-)
>>
> Agree. Need to make it clear, though, that 'message' is not
> necessarily the same as 'exception.args[0]'
>

If it was we wouldn't need an extra argument for it. :-)


>
>
>> Also I'd steer clear from calling the handler 'callback' -- maybe just
>> name
>> it 'exception_handler'?
>>
>>
>>       It's OK to call 'loop.stop()' or 'loop.call_*' methods from the
>>> handler.
>>>
>>>  Cool.
>>
>>
>>       If a user set handler raises an exception, that exception will be
>>>      handled by the default event loop exception handler (that will
>>>      simply log it)
>>>
>>>  Nice.
>>
>>
>>     - "loop.restore_default_exception_handler()"
>>>      Restores exception handler to the default one.
>>>      Default exception handler just logs the error with
>>>      'loop.logger.exception()'
>>>
>>>  Maybe instead of having a separate API for this rarely-used action, this
>> could be spelled as loop.set_exception_handler(None)?
>>
> Good. Since we always need to have at least default exception
> handler, using None in this context seems very logical.
>
>
>> A few questions:
>>
>> - Do we need an API to ask the loop for its current exception handler?
>>
> I thought about this, and my reasoning for not proposing
> 'loop.get_exception_handler()' was to keep the API simple.
>

Sure.


> Besides, let's pretend we have this API in place, and you
> can get the current handler. The getter will return the handler
> to the caller, and that handler, or callback object will make
> sense only to the application/code that set it in the first
> place.


Not necessarily, you know its signature.


> And I think in this case, it's better to force the client
> code to carefully use and track the calls to
> 'set_exception_handler()'.
>

Not necessarily. But I agree to leave this out unless and until an actual
real use case presents itself.



>  If
>> so, what should it return if no handler is set explicitly?
>>
> If we make the default handler a public API, then we can return
> a bound method. If we decide to hide it -- then 'None'.
>
>
>
>> - Should we allow multiple exception handlers, or just one? (I'd prefer
>> just one.)
>>
> The API will be more complex then, as we'll need functions to
> remove exception handlers, at least. Applications can always
> set one handler that will call other functions (as many as they
> need).
>

Right.

>
>
>> - Should we have a way to invoke the default handler explicitly? E.g. if
>> the user's handler doesn't want to do anything special, they could pass it
>> to the default handler instead of having to figure out how the default
>> handler logs things.
>>
> I think it's a good idea to let users trigger the default handler
> somehow.
>
> One option is to add it to the public API. But it may cause some
> confusion about when you should use it. Basically, the only place
> it should be used in, is a custom exception handler.
>

I suppose so. But this doesn't bother me much.


> Another option would be to let the custom handler simply re-raise
> the exception, but this way we'll mix exceptions originated *in*
> the handler with other exceptions, so I'd be -1 on this approach.
>

Agreed.


> And another option is to establish a protocol: if a custom handler
> returns an exception object, that object is passed to the default
> handler.
>

Eew. Special return values are very fragile in my experience.


> - Should we have a way to invoke the current handler explicitly? E.g. if
> there's user code that has encountered an exception and it wants that
> exception to be treated the same as the loop handles other exceptions.
>
>  -1 on this. Non-sophisticated code should just stick to the logging
> module. The kind of code that uses its custom error handlers, can
> develop its own facilities for error reporting.


I'm not sure. The default exception handler may, over time, develop some
useful custom behavior, and it's not like its signature is very complicated
or using it is fraught with problems. So I don't see much downside to
letting users call loop.default_exception_handler().

My suggestion would be two extra event loop methods:

loop.default_exception_handler(exception, message)
loop.call_exception_handler(exception, message)

The former is the default handler.

The latter calls the handler you set, if you set one, otherwise the default
handler.

-- 
--Guido van Rossum (python.org/~guido)

Reply via email to