[Python-ideas] Wild idea: Exception.format

Nick Coghlan ncoghlan at gmail.com
Sat Sep 19 03:43:05 CEST 2009

Yuvgoog Greenle wrote:
> I fail to see why you can't have both args and kwargs...
> class BaseException:
>     @classmethod
>     def format(cls, fmt, *args, **kwargs):
>         return cls(fmt.format(*args, **kwargs), *args, **kwargs)
> And concerning Gerog's actual question, I think this is a not uncommon
> pattern, but
>     raise Exception.format(...)
> doesn't sound good. It's not really as readable as
>     raise Exception(fmt.format(ext), ext)
> ilya suggested an almost ok direction but he doesn't define formats at
> runtime. So maybe instead we can make a factory for formatted exceptions.
> def formatted_exception(exception):
>     def format_and_return(fmt, *args, **kwargs):
>         return exception(fmt.format(*args, **kwargs), *args, **kwargs)
>     return format_and_return
> @formatted_exception
> class NotRegisteredError(LookupError): pass
> then the usage becomes:
> raise NotRegisteredError("Extension {0} not registered.", ext)

I like the class decorator idea (to avoid namespace conflicts on the
exception objects - cf. the dramas with ex.message). However, the above
would break exception handling since NotRegisteredError would refer to
the factory function instead of the exception that is actually thrown.

Combining it with Ilya's idea (by having the class decorator return a
new subclass rather than a factory function) gives something that should
work in practice:

def formatted_exception(exc):
  class FormattedExc(exc):
    def __init__(*args, **kwds):
      self, fmt, args = args[0], args[1], args[2:]
      super(FormattedExc, self).__init__(
            fmt.format(*args, **kwds), *args, **kwds)
    def __str__(self):
      return self.args[0]
    __name__ = exc.__name__
    __doc__ = exc.__doc__
    __module__ = exc.__module__
  return FormattedExc

class ExampleError(Exception): pass

>>> try:
...   raise ExampleError("Format: {}", "Value")
... except ExampleError as ex:
...   saved = ex
>>> saved
FormattedExc('Format: Value', 'Value')
>>> print(saved)
Format: Value
>>> saved.args[1]
>>> saved.__name__


Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-ideas mailing list