限制.py文件中的哪些类可从其他地方导入

时间:2014-03-06 16:13:16

标签: python plugins

我有一个python源文件,其中定义了一个类,另一个模块中的类导入了该文件。基本上,这个结构:

from parent import SuperClass
from other import ClassA

class ClassB(SuperClass):
    def __init__(self): pass

我想要做的是在这个模块中查找那里定义的所有类,并且只查找ClassB(并忽略ClassA)。 ClassA和ClassB都扩展了SuperClass。

原因是我有一个在运行时加载的插件目录,我通过对每个.py文件进行内省并加载扩展SuperClass的类来获得插件类的完整列表。在这种特殊情况下,ClassB使用插件ClassA为它做一些工作,因此依赖于它(同时,ClassA不依赖于ClassB)。问题是,当我从目录加载插件时,我得到2个ClassA实例,因为它从ClassA的文件中获取一个,而从ClassB的文件中获取一个。

对于包,有方法:

__all__ = ['module_a', 'module-b']

显式列出您可以导入的模块,但它存在于__init__.py文件中,每个插件都是.py文件,而不是它自己的目录。

那么问题是:我可以限制对.py文件中的类的访问,还是我必须使用自己的init文件使每个类都成为一个目录?或者,是否有其他一些聪明的方法可以区分这两个类?

1 个答案:

答案 0 :(得分:1)

你的意思是“对于包裹有方法......”。实际上,这适用于每个模块(__init__.py 一个模块,只有特殊的语义)。在插件模块中使用__all__即可。

但请记住:__all__仅限制您使用from xxxx import *导入的内容;您仍然可以访问模块的其余部分,并且无法使用标准的Python导入机制来避免这种情况。

如果您正在使用某种有效的内省技术(例如,在模块中探索命名空间然后从中导入类),您可以检查该类是否来自与模块本身相同的文件。

您也可以实现自己的导入机制(例如,使用importlib),但这可能有点过分......

编辑:对于“检查班级是否来自同一模块”:

假设我有两个模块,mod1.py

class A(object):
    pass

mod2.py

from mod1 import A

class B(object):
    pass

现在,如果我这样做:

from mod2 import *

我已导入AB。但...

>>> A
<class 'mod1.A'>
>>> B
<class 'mod2.B'>

如你所见,这些课程带有关于它们起源的信息。实际上你可以马上检查一下:

>>> A.__module__
'mod1'
>>> B.__module__
'mod2'

使用这些信息可以轻松区分它们。