On 28.06.2017 15:26, Nick Coghlan wrote:
1. In 3.3+ you can just catch ImportError, check "exc.name", and
re-raise if it's not for the module you care about
I see, didn't know that one. I gave it a try and it's not 100% the
behavior I have expected, but one could workaround if the valid
package structure is known. Not sure for certain.
"from foo.bar.baz import abc" can yield to "exc.name" being one of
"foo", "foo.bar" or "foo.bar.baz". Not perfect but sort of doable.
2. There's a reasonable case to be made that importlib should include
an ImportError -> RuntimeError conversion around the call to
loader.exec_module (in the same spirit as PEP 479). That way, in:
import fallbacks.MySpecialLib as myspeciallib
any caught ImportError would relate to "myspeciallib", while uncaught
ImportErrors arising from *executing* "myspeciallib" will be converted
to RuntimeError, with the original ImportError as their __cause__.
Generally changing the behavior for ImportError doesn't sound like
it would work for all projects out there.
For fallback imports, I am on your side, that's a real use case
which can be solved by changing the behavior of ImportErrors. But
for all imports? I don't know if that's good idea.
[People should use tools, guard against bugs and try to avoid mistakes.]
Sure, but I don't see who this can help, if I use third-party code.
The cases, which I described in the original post, were simple
cases, where we catch too many exception. So, I don't even have the
chance to see the error, to file a bug report, to issue a pull
request, etc. etc.
The cases I'm interested in are the ones where you're either
developing some kind of framework and you need to code that framework
defensively to guard against unexpected failures in the components
you're executing (e.g. exec_module() in the PEP 451 import protocol),
or else you're needing to adapt between two different kinds of
exception reporting protocol (e.g. KeyError to AttributeError and
I am unsure what you mean by those abstract words "framework" and
"components". But let me state it in different words: there are raisers
and catchers which do the respective thing with exceptions.
If you control the code on both sides, things are easy to change.
Pre-condition: you know the bug in the first place, which is hard
when you catch too much.
If you control the raiser only, it doesn't help to say: "don't make
mistakes, configure systems right, code better, etc." People will
make mistakes, systems will be misconfigured, linters don't find
If you control the catcher only, you definitely want to narrow down
the amount of caught exceptions as far as possible. This was the
original intend of this thread IIRC. This way you help to discover
bugs in raising code. Addition benefit, you catching code reacts
only to the right exceptions.
One word about frameworks here. Django, for instance, is on both
sides. The template engine is mostly on the catchers side, whereas
the database layer is on the raisers side.
I get the feeling that the solutions presented here are way too
complicated and error-prone. My opinion on this topic still is that
catching exceptions is not mandatory. Nobody is forced to do it and
it's even better to let exceptions bubble up to visualize bugs. If
one still needs to catch them, he should only catch those he really,
really needs to catch and nothing more. If this cannot be improved
sensibly, well, so be it. Although I still don't find the argument
presented against "catching shallow exception" a little bit too
abstract compared to the practical benefit. Maybe, there's a better
solution, maybe not.