[Python-3000] exception-swallowing behaviour of hasattr
Guido van Rossum
guido at python.org
Tue Jan 22 16:36:12 CET 2008
IMO (1) or (2) are both acceptable, but I'd prefer (2): swallow
'Exception'. There's a reason why hasattr() is different from
getattr() with a default value; it's too early for me to explain it
clearly, but I know it was discussed and argued at length when
hasattr() was introduced.
I don't see why AssertionError ought to be treated differently than
TypeError or any other "regular" error. The key goal here is to avoid
swallowing KeyboardInterrupt, and to a lesser extend SystemExit.
--Guido
On Jan 21, 2008 10:47 PM, Dwayne C. Litzenberger <dlitz at dlitz.net> wrote:
> This issue has been raised before, but Guido thought that changing things
> in 2.x would break too much code. See:
>
> http://mail.python.org/pipermail/python-dev/2005-February/051770.html
> http://mail.python.org/pipermail/python-dev/2005-December/058498.html
> http://bugs.python.org/issue504714
>
> I'm bringing this up again because the arguments I've seen in favour of
> fixing hasattr have been fairly weak, and I'd like to raise some stronger
> ones. Also, I haven't seen this issue considered specifically in the
> context of Python 3000.
>
> The problem is that hasattr behaves just like the following code:
>
> def hasattr(obj, name):
> try:
> getattr(obj, name)
> return True
> except:
> return False
>
> In Python 3000, all exceptions inherit from BaseException, so this is
> equivalent to:
>
> def hasattr(obj, name):
> try:
> getattr(obj, name)
> return True
> except BaseException:
> return False
>
> There are three major things that are broken by this behaviour, which I
> don't think have been explicitly mentioned:
>
> 1. If the Python interpreter receives SIGINT (usually triggered by
> Ctrl-C) while executing obj.__getattr__ (or anything it calls),
> hasattr silently returns False and the program continues running.
>
> Cause: KeyboardInterrupt is swallowed.
>
> 2. If sys.exit is called within obj.__getattr__, hasattr silently
> returns False and the program continues running.
>
> Cause: SystemExit is swallowed.
>
> 3. If an assert statement fails within obj.__getattr__, hasattr
> silently returns False and the program continues running.
>
> Cause: AssertionError is swallowed.
>
> Also, because getattr(x,y,z) swallows only AttributeError, users naturally
> expect hasattr to behave the same way. (This argument has been raised
> before.)
>
> I propose a few alternate behaviours for hasattr (and their consequences):
>
> 1. Swallow only AttributeError.
>
> - KeyboardInterrupt, SystemExit, and AssertionError are all passed
> through, solving all three of the above problems.
>
> - The behaviour of hasattr is made consistent with getattr(x,y,z).
>
> 2. Swallow only Exception.
>
> - KeyboardInterrupt and SystemExit are passed through, but
> AssertionError is still swallowed.
>
> - Breaks less code than the previous option.
>
> 3. Swallow Exception unless it's an AssertionError.
>
> - KeyboardInterrupt, SystemExit, and AssertionError are all passed
> through, solving all three of the above problems.
>
> - Kind of ugly.
>
> 4. Swallow everything except KeyboardInterrupt and SystemExit.
>
> - AssertionError is still swallowed, but the other problems are
> fixed and this probably won't break any existing code.
>
> I looked at bltinmodule.c, and any of these would be trivial to implement.
>
> Ideally, I would like to see the first option implemented in Python 3000
> and one of the other options implemented in 2.x.
>
> --
> Dwayne C. Litzenberger <dlitz at dlitz.net>
> _______________________________________________
> Python-3000 mailing list
> Python-3000 at python.org
> http://mail.python.org/mailman/listinfo/python-3000
> Unsubscribe: http://mail.python.org/mailman/options/python-3000/guido%40python.org
>
--
--Guido van Rossum (home page: http://www.python.org/~guido/)
More information about the Python-3000
mailing list