[Python-3000] exceptions with keyword arguments
tomer filiba
tomerfiliba at gmail.com
Wed May 17 19:29:01 CEST 2006
hi all
i would like to suggest changing the base-exception class, whatever
it may be (Exception/BaseException) to work with keyword arguments
instead of positional ones.
instead of
try:
...
except IOError, ex:
print ex[1]
# or
except IOError, (code, text, filename):
...
# which means changes to code/text/filename do not change
# the exception object
use
try:
raise IOError(filename = "lala", code=17, text="blah blah blah")
except IOError, ex:
ex.code = 18
raise
raise IndexError("invalid index", index = the_index)
raise KeyError("key not found", key = the_key)
raise AttributeError("attribute not found", name = name)
where the new exception can be something like
class Exception:
def __init__(self, message = None, **kw):
self._message = message
self.__dict__.update(kw)
def __repr__(self):
attrs = sorted("%s = %r" % (k, v)
for k, v in self.__dict__.iteritems()
if not k.startswith("_"))
return "<%s(%s, %s)>" % (self.__class__.__name__,
self._message, ", ".join(attrs))
class IOError(Exception):
pass
raise IOError(code = 17, text = "EBLAH", filename = "lalala")
the builtin errors might want to enforce an "exception signature",
class ExceptionSignature(Exception):
attributes = []
def __init__(self, *args, **kw):
for name in self.attributes:
assert name in kw, "expected an attribute named %s" % (name,)
Exception.__init__(self, *args, **kw)
class IOError(ExceptionSignature):
attributes = ["code", "text", "filename"]
or something like that, so the attributes of the exception are part
of its official interface.
rationale:
* today, AttributeError's are raised as
AttributeError("%s object has no attribute %s" % ...)
which means analyzing the exception requires parsing text!
* IOError (among others), for instance, does nasty and not-so-well documented
overloading of named/positional arguments: when you pass 1-3 arguments,
they are stored in .args, but also in .errno, .strerror, and
.filename. if you pass
more than 3 arguments, the attributes are all set to None and only
.args is filled.
yuck.
you can see this for reference:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496698
----
that said, i would also want to introduce ArgumentError. there are
many times just a ValueError isn't enough. instead, having a builtin
ArgumentError would made things more clear:
def write_to_file(the_file):
if the_file.closed:
raise ArgumentError("the file must be open", name = "the_file")
the_file.write(...)
and with ArgumentError included, calling functions with invalid
signatures would also raise ArgumentError. TypeError is quite
silly in this case, as it has nothing to do with the *type* of
the function or its arguments.
>>> def f(a): pass
>>> f(1,2)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
*TypeError*: f() takes exactly 1 argument (2 given)
>>> type(f)
<type 'function'> # like any other function
TypeError is too-broadly overloaded this way.
-tomer
More information about the Python-3000
mailing list