[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