遍历动态导入模块中的类

27 投票
3 回答
32986 浏览
提问于 2025-04-17 03:16

我有一个来自子包的模块是动态导入的;我该如何遍历它里面的类呢?

我一直在这样导入模块并列出名称:

package = current_module.__name__
package = package[:package.rindex(".")] # get the package
package = "%s.sub.%s"%(package,name) # make the name of the child
print "(loading package %s)"%package
module = __import__(package) # this succeeds
for name,obj in inspect.getmembers(module):
    print name,type(obj)

这样做只会打印模块的属性,而不会显示模块定义的类类型:

__builtins__ <type 'dict'>
__doc__ <type 'NoneType'>
__file__ <type 'str'>
__name__ <type 'str'>
__package__ <type 'NoneType'>
__path__ <type 'list'>
imported_package <type 'module'>

看起来我的类不在 __dict__ 里面,除非 fromlist 不是空的!不过,从列表里的值似乎并没有被验证;像 [""] 这样的值也能正常工作,结果类就突然出现了!

有人能解释一下这是为什么吗?

(标准的ubuntu python 2.7.1+ (r271:86832))

3 个回答

4

方法一:

import inspect
import mymodule

for name, obj in inspect.getmembers(mymodule):
    if inspect.isclass(obj):
        do stuff...

方法二:

desired_classes = [obj for name, obj in somemodule.__dict__.items() if isinstance(obj, DesiredType)]

方法三:

在你想要循环的模块里面:

文件:mymodule.py

class Dog:
    VOICE = 'haou'


class Cat:
    VOICE = 'meew'


class ImNotIncluded:
    VOICE = 'what a shame'


__all__ = ['Dog', 'Cat']

>>> from mymodule import *
>>> Dog.VOICE
'haou'
>>> Cat.VOICE
'meew'
>>> ImNotIncluded.VOICE
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
NameError: name 'ImNotIncluded' is not defined

现在要进行循环,你可以这样做:

>>> for cls in map(mymodule.__dict__.get, mymodule.__all__): cls
...
<class 'mymodule.Dog'>
<class 'mymodule.Cat'>
 
6

如果你在要导入的模块里定义了 __all__,这个定义会告诉程序哪些内容可以被导出。这样的话,你就可以专门选择这些内容来进行遍历。

map(module.__dict__.get, module.__all__)
57

举个例子:我们可以创建一个字典,用来把名字和类对应起来:

dict([(name, cls) for name, cls in mod.__dict__.items() if isinstance(cls, type)])

这里的 mod 是已经加载的模块。

撰写回答