isinstance() not recognizing an instance correctly (python bug?)

Fernando Pérez fperez528 at yahoo.com
Wed May 8 13:56:36 EDT 2002


Martin v. Löwis wrote:

> Fernando Perez <fperez528 at yahoo.com> writes:
> 
>> So both the user-defined one and the internal one have been imported
>> via the same statement. Note however that as I said, the interactive
>> user code is run in a closed namespace, which is what (I think)
>> causes the behavior. I could well be confused though.
> 
> I guess you need to explain in more detail what a "closed namespace"
> is. Does it share sys.modules with the rest of the interpreter?
> 
> If not, that would indeed explain the problem.
> 
> You should compute and print the id of class Struct at both places,
> and see whether they are identical. If not, it is not surprising that
> the isinstance check fails - you would have two different classes that
> just happen to have the same name.

Here's the output. Indeed they have a different id for the Struct class, but 
the funny thing is that sys.modules shows the same id both for the 
interactive and internal sides.

[python]> ip
Python 2.2 (#1, Feb 24 2002, 16:21:58)
Type "copyright", "credits" or "license" for more information.

IPython 0.2.12pre13 -- An enhanced Interactive Python.
?       -> Introduction to IPython's features.
@magic  -> Information about IPython's 'magic' @ functions.
help    -> Python's own help system.
object? -> Details about 'object'. ?object also works, ?? prints more.

In [1]: from Struct import Struct

In [2]: s=Struct(a=1)

In [3]: print id(Struct)
136214948

In [4]: print id(sys.modules )
134532788

In [5]: s
Out[5]:
Argument passed belongs to class: Struct.Struct
Is arg a Struct (via isinstance)? 0
id of Struct class: 135905636
id of sys.modules : 134532788
Struct({'a': 1})



By 'in a closed namespace' I mean that all user input is executed via the 
following code (my shell is a subclass of the code.py stuff, the code below 
is copied from code.py):

    def runcode(self, code):
        """Execute a code object.

        When an exception occurs, self.showtraceback() is called to
        display a traceback.  All exceptions are caught except
        SystemExit, which is reraised.

        A note about KeyboardInterrupt: this exception may occur
        elsewhere in this code, and may not always be caught.  The
        caller should be prepared to deal with it.

        """
        try:
            exec code in self.locals
        except SystemExit:
            raise
        except:
            self.showtraceback()
        else:
            if softspace(sys.stdout, 0):
                print


The locals dict referenced by this is given in the the following constructor 
in my class:

        code.InteractiveConsole.__init__(self,locals = user_ns)

where user_ns is initially an almost empty dict. So all user code is executed 
in user_ns, not in __main__. But looking at code.py, a similar thing is done 
if you don't specify locals (a new dict is created for user execution), so I 
guess this problem will happen to anyone subclassing InteractiveConsole.

If you really need, I can try to write a new simple subclass of 
InteractiveConsole showing the problem, which I'm getting more and more 
convinced should at least be documented as a failure mode of isinstance().

Thanks for the help,

f.



More information about the Python-list mailing list