[ python-Bugs-1249615 ] isinstance() fails depending on how modules imported
SourceForge.net
noreply at sourceforge.net
Thu Aug 11 19:43:20 CEST 2005
Bugs item #1249615, was opened at 2005-08-01 10:54
Message generated for change (Comment added) made by tjreedy
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1249615&group_id=5470
Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Python Interpreter Core
Group: Python 2.4
Status: Closed
>Resolution: Invalid
Priority: 5
Submitted By: Hugh Gibson (hgibson50)
Assigned to: Nobody/Anonymous (nobody)
Summary: isinstance() fails depending on how modules imported
Initial Comment:
I have found an inconsistency with instance type
checking dependent on how modules are imported.
Using Windows 2000, Python 2.4.1.
Source files are attached. Unzip preserving paths. To
run, open a cmd window and set PythonPath to the
location of the "system" folder. Run ServerRun.py.
The program creates two class instances in two different
modules, then calls a class function on one instance
which takes as parameter the second instance. A call to
isinstance to check if the parameter is of the correct
class fails.
If a parameter is passed to ServerRun.py then the class
module is imported in a different way (specifying the
path to the class) and the isinstance check succeeds.
The output shows that before the call to the class
function, an isinstance() call succeeds in both cases.
There is obviously an easy fix in code, but I think that
isinstance checking should not depend on how modules
are imported. And, if I am using an incorrect module
import sequence, that sequence should be disallowed.
Sample output (also showing Windows 2000 version) is:
Microsoft Windows 2000 [Version 5.00.2195]
(C) Copyright 1985-2000 Microsoft Corp.
C:\system\server>set pythonpath=c:\system
C:\system\server>serverrun
ServerRun:
oNew.__class__ ==
<class 'Stream.Stream.CElement'>
Stream.CElement ==
<class 'Stream.Stream.CElement'>
isinstance(oNew, Stream.CElement) == True
AddField():
oNew.__class__ ==
<class 'Stream.Stream.CElement'>
CElement ==
<class 'server.Stream.Stream.CElement'>
isinstance(oNew, CElement) == False
C:\system\server>serverrun 1
ServerRun:
oNew.__class__ ==
<class 'server.Stream.Stream.CElement'>
Stream.CElement ==
<class 'server.Stream.Stream.CElement'>
isinstance(oNew, Stream.CElement) == True
AddField():
oNew.__class__ ==
<class 'server.Stream.Stream.CElement'>
CElement ==
<class 'server.Stream.Stream.CElement'>
isinstance(oNew, CElement) == True
C:\system\server>
----------------------------------------------------------------------
>Comment By: Terry J. Reedy (tjreedy)
Date: 2005-08-11 13:43
Message:
Logged In: YES
user_id=593130
adding the resolution as 'invalid' based on the discussion here
and elsewhere
----------------------------------------------------------------------
Comment By: Hugh Gibson (hgibson50)
Date: 2005-08-03 03:45
Message:
Logged In: YES
user_id=732318
Thanks for the concise example.
I can see why our code fails. If I check each class instance
using its own function then it will succeed, but if I check
using another instance's function then it fails because as you
say the module is imported differently.
Putting a statement at the start of the class module:
print __name__
shows two imports of the class module in the failure mode,
with different names.
So an easy cross-check to make sure we are being
consistent about importing is:
assert(__name__ == "server.Stream.Stream")
This fires if the incorrect sequence is used to import the
module.
This is a simple check which can be added to every module
and will guard against incorrect imports in future.
I suppose that I can't complain about flexibility in Python
which allows all sorts of tricks. In this case I was handed just
a bit too much rope. But the simple assert, added to our
coding standards and code, will prevent any problems in
future.
Thanks.
Hugh
----------------------------------------------------------------------
Comment By: Walter Dörwald (doerwalter)
Date: 2005-08-02 09:14
Message:
Logged In: YES
user_id=89016
The problem is not isinstance() per se, but the fact that
you import one Python script as two different modules. A
simple demo might look like this:
class Foo: pass
import bug
print isinstance(Foo(), bug.Foo)
Put this in bug.py and run "python bug.py" and you'll get:
True
False
So I think this bug should be closed.
----------------------------------------------------------------------
Comment By: Hugh Gibson (hgibson50)
Date: 2005-08-02 09:00
Message:
Logged In: YES
user_id=732318
The case I found here is particularly worrying because I'm
doing the isinstance() check in the module that contains the
class. The success of the check depends on how that
module was imported into other modules. The two cases are:
from server.Stream import Stream
from Stream import Stream
We found this problem in a large application under
development. Unit testing of the class succeeded because of
the way the class module was imported. But the application
itself failed because of the way one module imported the
class module. The failure was obvious in our application but
clearly there may be subtle failure modes - for example,
exception handling may use isinstance() internally to see if
an exception is an instance of a given class.
I've modified the code and added some more testing which
shows clearly that it's not the class object itself which is the
problem, but when you have a class method which accepts
an instance of the class as a parameter. Any test of the
class of that parameter will fail if the first instance is created
in one module and the second instance is created in another
module, and they import the class module differently.
Note that it's not restricted to isinstance() - checking
__class__ fails as well.
Also, in both of the modules that import the class module,
isinstance() checking succeeds. There is a false sense of
security that isinstance() checking will be OK.
Modifed code attached.
Hugh
----------------------------------------------------------------------
Comment By: Reinhold Birkenfeld (birkenfeld)
Date: 2005-08-02 05:19
Message:
Logged In: YES
user_id=1188172
This has bitten me too at one time.
When you import a module from a package starting from
different sys.path entries, you will end up with two
different modules in sys.modules.
This seems to be intended behaviour, but I don't know enough
about it to close this.
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1249615&group_id=5470
More information about the Python-bugs-list
mailing list