This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: exception cannot be new-style class
Type: Stage:
Components: Interpreter Core Versions: Python 2.5
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: gvanrossum Nosy List: brett.cannon, doerwalter, facundobatista, gvanrossum, jhylton, loewis, magnusheino, pje, robey1
Priority: normal Keywords:

Created on 2002-02-17 20:09 by magnusheino, last changed 2022-04-10 16:05 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
raise-patch jhylton, 2002-04-05 23:38
diff.txt doerwalter, 2002-07-11 16:12 Another patch enabling new style exceptions
test.py doerwalter, 2002-07-11 17:07
Messages (16)
msg9293 - (view) Author: Magnus Heino (magnusheino) Date: 2002-02-17 20:09
[magnus@gills magnus]$ python2.2
Python 2.2 (#1, Jan 26 2002, 14:27:24)
[GCC 2.96 20000731 (Red Hat Linux 7.1 2.96-98)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class foo(object):
...     pass
...
>>> raise foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: exceptions must be strings, classes, or instances, not foo
>>>
msg9294 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2002-02-17 23:44
Logged In: YES 
user_id=21627

Interesting. I think we need to deprecate, then remove
string exception before allowing arbitrary objects as
exceptions. Or we could allow strings to be caught either by
__builtin__.str, or by an identical string.
msg9295 - (view) Author: Jeremy Hylton (jhylton) (Python triager) Date: 2002-04-05 23:38
Logged In: YES 
user_id=31392

Martin, I think the attached patch is sufficient.  It checks
object type's for Py_TPFLAGS_HEAPTYPE.  I believe this is
the current way to spell "new-style class" although the
spelling is odd if that's the meaning <0.2 wink>.

If this patch makes sense to you, I'll flesh it out with
some test cases and check it in.
msg9296 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2002-04-05 23:44
Logged In: YES 
user_id=21627

I thought the agreement was that this is not a bug: You
cannot really expect exceptions to work unless you inherit
from Exception.
msg9297 - (view) Author: Jeremy Hylton (jhylton) (Python triager) Date: 2002-04-05 23:49
Logged In: YES 
user_id=31392

I don't realize there was agreement on this.  (I didn't 
follow the discussion closely.)  I don't understand why 
exceptions need to pass an isinstance() test on Exception.  
It didn't used to be this way, and it makes it hard to 
convert a module using __metaclass__ = type.
msg9298 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2002-04-06 00:07
Logged In: YES 
user_id=6380

Sorry, HEAPTYPE is not the proper way to check for a
new-style class; it would exclude any new-style classes
defined by C code.  I also think that if you want to do this
it should done properly, and allow "raise C, C()" as well.

At best there's agreement that it's not worth trying to fix
Python to allow new-style classes as exceptions when we're
also trying to encourage that exceptions derive from
Exception.

If your module declares its exceptions as deriving from
Exception, a __metaclass__ = type should not have any effect
on the exceptions you declare.  So I'm not sure what your
problem is?

Here's another idea for a patch: a new-style class is
allowed as long as it also inherits from Exception.  (This
is possible!)
msg9299 - (view) Author: Walter Dörwald (doerwalter) * (Python committer) Date: 2002-07-11 16:12
Logged In: YES 
user_id=89016

What about the following patch (diff.txt):

It allows new style objects as exceptions and makes catching
exceptions by basetype possible:
    class newint(int):
        pass
    try:
        raise newint(42)
    except int, exc:
        print exc

With this patch subinstances of str become raisable and will
be caught be type not identity. This could be changed to
explicitely forbid str subinstances.

And
  raise type(None), None
becomes ambiguous: It is interpreted as
  raise type(None)
i.e. it raises the type(None) object as an exception, not
the object None (which is of type type(None))

As soon as Exception is a new style class we could limit the
allowed objects to (sub)instances of Exception.
msg9300 - (view) Author: Walter Dörwald (doerwalter) * (Python committer) Date: 2002-07-11 17:07
Logged In: YES 
user_id=89016

test.py is a little script that executes various test cases.
msg9301 - (view) Author: PJ Eby (pje) * (Python committer) Date: 2002-07-11 20:12
Logged In: YES 
user_id=56214

Just to make things even more interesting, the current
'raise' code *will* let you raise a new-style instance that
derives from 'tuple'...  of course, what it actually raises
is the first element of said tuple-like thing.

It seems to me that the very first thing that should be
checked is whether the first argument to 'raise' is an
instance of Exception, and if so, take its type and go from
there.  This would support both old and new-style instances
of Exception subclasses, and I believe is the recommended
approach to using 'raise'.  (I.e., raise an instance of
something that subclasses Exception.)  All the other items
like strings, tuples, etc., should be checked *after* a
check for the "standard" approach, yes?
msg9302 - (view) Author: Facundo Batista (facundobatista) * (Python committer) Date: 2004-11-25 02:05
Logged In: YES 
user_id=752496

Reproduced the bug in Py2.3. I think that this is a bug, at
least because we "encourage" users to derive exceptions from
Exception, so they should be able to not do it.

The moment we say that they "must" derive from Exception,
this can be closed (of course, this is my *very* personal
opinion, ;)
msg9303 - (view) Author: Robey Pointer (robey1) Date: 2004-12-15 21:08
Logged In: YES 
user_id=1179122

This caused me an hour of debugging a few nights ago.  When
using unified types, it's very confusing to find that not
only does Exception not follow new-style object semantics,
but it *can't*.  Doing the obvious hack:

class MyException (Exception, object):
    pass

does not work!  The interpreter (2.3) refuses to let you
raise a unified-type object.  And if you subclass
exclusively from Exception, type(obj) returns 'instance'
instead of the class (due to being an old-style object).

Please fix this for 2.4!
msg9304 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2004-12-15 21:59
Logged In: YES 
user_id=21627

Whatever the solution to this problem, it is for sure that
2.4.x won't see it, because it will be a new feature.
msg9305 - (view) Author: Robey Pointer (robey1) Date: 2004-12-15 23:39
Logged In: YES 
user_id=1179122

Let me try to rephrase the problem so that it's obvious that
this is a bug, and not a feature:

'type(e)' on an exception will not work in 2.3, and cannot
be made to work from within python code.  There's no way to
throw an exception (ie an object with Exception in its
ancestor list) that 'type(e)' will work on. :(
msg9306 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2004-12-16 13:00
Logged In: YES 
user_id=21627

This statement, as literally made, is incorrect:

>>> class X(Exception):
...   pass
...
>>> e=X()
>>> type(e)
<type 'instance'>
>>> raise e
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
__main__.X: <__main__.X instance at 0x401f2b4c>

In this example, type(e) works, and x is an object which has
Exception among its base classes. Still, I can throw x,
despite your claim that I cannot.

Even if I interpret your statement more literally (i.e. that
you are talking about objects for which type(e) is a
new-style class): Why do you think this statement explains
there is a bug?

As for why it is a new feature: it currently doesn't work,
and anybody trying it will quickly find out that it doesn't
work. The language reference says it doesn't work. The
TypeError you get says it doesn't work. So that it doesn't
work is clearly intentional; changing it will be a new feature.

Notice that it is very difficult to implement this feature,
as something needs to happen with strings and subtypes of
str. Currently, string exceptions are caught by identity. If
arbitrary objects can be used as exceptions, then strings
should also be caught by type, not by identity; this is a
backwards-incompatible change.

A clean solution would be to deprecate string exceptions in
2.5, completely ban them in 2.6, and allow arbitrary objects
to act as exceptions in 2.7. 

Please do read the entire thread of this RFE.
msg9307 - (view) Author: Robey Pointer (robey1) Date: 2004-12-17 20:46
Logged In: YES 
user_id=1179122

(I wish we could do this in email instead of cluttering up
an already-messy bug...)

Forget about throwing non-Exception-based objects: it's a
red herring.  The bug to focus on is the title: "exception
cannot be new-style class".

Bottom line:  This subclass of Exception can not be raised
in python 2.3:

class MyException (Exception, object): pass

pje's comment below from (2002-07-11 13:12) is a nice
summary of how to solve it.
msg9308 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2006-03-01 04:34
Logged In: YES 
user_id=357491

rev. 42711 (PEP 352 implementation) made built-in exceptions
new-style.
History
Date User Action Args
2022-04-10 16:05:00adminsetgithub: 36116
2002-02-17 20:09:57magnusheinocreate