其用意是为了实现某种插件框架,其中插件是相同的基类的子类(即B)(即A)。 基类装载有标准进口,而子类装载有从公知的包的路径imp.load_module()(即PKG)。
pkg/
__init__.py
mod1.py
class A
mod2.py
class B(pkg.mod1.A)
这与真正的子类,即工作得很好,
# test_1.py
import pkg
from pkg import mod1
import imp
tup = imp.find_module('mod2', pkg.__path__)
mod2 = imp.load_module('mod2', tup[0], tup[1], tup[2])
print(issubclass(mod2.B, mod1.A)) # True
但测试的基类本身时,问题就来了,
# test_2.py
import pkg
from pkg import mod1
import imp
tup = imp.find_module('mod1', pkg.__path__)
mod0 = imp.load_module('mod1', tup[0], tup[1], tup[2])
print(issubclass(mod0.A, mod1.A)) # False
但mod0.A和mod1.A实际上是来自同一个文件(PKG / mod1.py)同一类。
这个问题出现在两个蟒蛇2.7和3.2。
现在的问题是两方面的,一个),它是一个期望的特性或issubclass()的一个bug,和b)如何摆脱这种不改变PKG的内容是什么?
他们不是同一类。 他们用相同的代码创建,但因为你执行的代码两次(一次是在进口和一次load_module)你会得到两个不同的类的对象。 issubclass
是比较类对象的身份和他们是不同的。
编辑:既然你不能靠issubclass
,一个可能的选择是创建将由派生类继承基类的一个独特的属性。 此属性将存在于类的拷贝。 然后,您可以测试的属性。
class A:
isA = True
class B(A):
pass
class C:
pass
def isA(aclass):
try:
return aclass.isA
except AttributeError:
return False
print isA(A)
True
print isA(B)
True
print isA(C)
False
因为我花了一些时间与这摆弄,我想我会分享我的解决方案:
import inspect
...
def inherits_from(child, parent_name):
if inspect.isclass(child):
if parent_name in [c.__name__ for c in inspect.getmro(child)[1:]]:
return True
return False
print inherits_from(possible_child_class, 'parent_class')
#True
当然,这只是真正检查该子类从类调用继承parent_class
,但我的目的(而最让我怀疑),这很好。
注:本如果返回false possible_child_class
是parent_class的实例,由于[1:]
。
#!/usr/bin/env python
import os
import sys
import pkg
from pkg import mod1
import imp
def smart_load_module(name, path):
# get full module path
full_path = os.path.abspath(os.path.join(path[0], name))
for module_name, module in sys.modules.items():
# skip empty modules and ones without actual file
if not module or not hasattr(module, '__file__'):
continue
# remove extension and normalize path
module_path = os.path.abspath(os.path.splitext(module.__file__)[0])
if full_path == module_path:
return module
# if not found, load standard way
tup = imp.find_module(name, path)
return imp.load_module(name, tup[0], tup[1], tup[2])
if __name__ == '__main__':
mod00 = smart_load_module('mod1', pkg.__path__)
print(issubclass(mod00.A, mod1.A)) # True
tup = imp.find_module('mod1', pkg.__path__)
mod0 = imp.load_module('mod1', tup[0], tup[1], tup[2])
print(issubclass(mod0.A, mod1.A)) # False
这对我的作品。 我的完整路径sys.modules中搜索类,并返回加载的情况下,如果任何发现。