issubclass()返回关于从不同的路径导入同一类假(issubclass() returns

2019-09-19 09:59发布

其用意是为了实现某种插件框架,其中插件是相同的基类的子类(即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的内容是什么?

Answer 1:

他们不是同一类。 他们用相同的代码创建,但因为你执行的代码两次(一次是在进口和一次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


Answer 2:

因为我花了一些时间与这摆弄,我想我会分享我的解决方案:

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:]



Answer 3:

#!/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中搜索类,并返回加载的情况下,如果任何发现。



文章来源: issubclass() returns False on the same class imported from different paths
标签: python class