[Python-Dev] Chaining try statements: eltry?
Thomas Lotze
thomas at thomas-lotze.de
Wed Jul 6 20:07:45 CEST 2005
Hi,
this is my first message to this list, so let me say hello first.
I want to ask what you think about introducing a keyword 'eltry' which
would be the counterpart of 'elif' for try statements. This had been
suggested before on python-list a couple of years ago by Jonathan
Gardner, but nothing (that I could find) seems to have come of it.
Starting from PEP 341, the try statement might be extended to
try_stmt: 'try' ':' suite
(
(except_clause ':' suite)+
(
'eltry' ':' suite
(except_clause ':' suite)+
)*
['else' ':' suite]
['finally' ':' suite]
|
'finally' ':' suite
)
where lines 4 through 7 would be an addition to the definition given in
the PEP. Admittedly, this looks somewhat complex, but I don't think it
actually is. (And while an new keyword always means potentially breaking
code, 'eltry' doesn't seem to me a likely identifier chosen by
programmers - YMMV.)
This extension would be useful whenever a suite of statements is to be
terminated as soon as one of them raises an exception, and the
programmer is interested in handling those individually. Without 'eltry'
the choices are:
- Stack conventional try statements, each inside the else clause of
the one before. This causes deep nesting, and while typical nesting
depths won't be as great as they might become with stacked if
statements, it is annoying and ugly IMO.
- Run all statements at once and put all exception handlers outside the
suite. This yields code that is harder to read than necessary as some
handlers will be written far from the statement where the exception
they handle is raised. Moreover, if more than one statement may raise
a particular exception, some effort is required to find out which one
did it if there is only one handler for that exception.
- Break up the suite into separate try statements. While this may result
in well readable code if each handler breaks out of the block
containing the whole run of try statements, it requires some mechanism
(such as a wrapper try statement or a separate function that may quit
anytime) if exiting the current block is not desired.
- Something else, in which case I'm looking forward to learning
something new about Python ;o)
An example would be a filter chain:
def use_eltry(data):
# decode as far as possible
try:
data = foo_decode(data)
except ValueError:
print "Data seems not to be foo encoded."
eltry:
data = bar_decode(data)
except ValueError:
print "Foo decoded data seems not to be bar encoded."
eltry:
data = baz_decode(data)
except ValueError:
print "FooBar decoded data seems not to be baz encoded."
# whatever data is by now, do something with it
do_something(data)
def use_stacking(data):
# decode as far as possible
try:
data = foo_decode(data)
except ValueError:
print "Data seems not to be foo encoded."
else:
try:
data = bar_decode(data)
except ValueError:
print "Foo decoded data seems not to be bar encoded."
else:
try:
data = baz_decode(data)
except ValueError:
print "FooBar decoded data seems not to be baz encoded."
# whatever data is by now, do something with it
do_something(data)
def use_single_handler(data):
# decode as far as possible
try:
data = foo_decode(data)
data = bar_decode(data)
data = baz_decode(data)
except ValueError:
print "Data could not be decoded, can't tell you why easily."
# whatever data is by now, do something with it
do_something(data)
def use_custom_exception(data):
# decode as far as possible
try:
try:
data = foo_decode(data)
except ValueError:
print "Data seems not to be foo encoded."
raise
try:
data = bar_decode(data)
except ValueError:
print "Foo decoded data seems not to be bar encoded."
raise
try:
data = baz_decode(data)
except ValueError:
print "FooBar decoded data seems not to be baz encoded."
raise
except ValueError:
pass
# whatever data is by now, do something with it
do_something(data)
def use_function(data):
# decode as far as possible
def helper():
try:
data = foo_decode(data)
except ValueError:
print "Data seems not to be foo encoded."
return
try:
data = bar_decode(data)
except ValueError:
print "Foo decoded data seems not to be bar encoded."
return
try:
data = baz_decode(data)
except ValueError:
print "FooBar decoded data seems not to be baz encoded."
return
helper()
# whatever data is by now, do something with it
do_something(data)
Does this seem contrived? (Obviously, I don't think so.) It would be
nice to hear your opinions and, if you don't agree with the proposal,
learn what is bad about it.
--
Viele Grüße,
Thomas
More information about the Python-Dev
mailing list