pkgutil获取包里面的所有模块列表,__import__和importlib.import_module

 

1、获取模块中的属性

想要获取clazz包中a模块的所包含的方法,可以直接使用dir这个函数,可以看到show 这个方法已经包含在其中

from clazz import a

print(dir(a))

"""
['__builtins__', '__cached__', '__doc__', '__file__', 
'__loader__', '__name__', '__package__', '__spec__', 'show']
"""
"""

2、获取包中的属性

如果我要获取clazz 包中所有模块,直接使用dir 并没有


import clazz

print(dir(clazz))

"""
['__builtins__', '__cached__', '__doc__', '__file__', 
'__loader__', '__name__', '__package__', '__path__', '__spec__']
"""

既然,模块可以查看其中包含的属性,而包其实就是一个文件夹
那么,先获取包文件夹下的所有模块文件,再逐个导入模块,最后也可以获取模块中的属性。


import os
import importlib


def get_modules(package="."):
    """
    获取包名下所有非__init__的模块名
    """
    modules = []
    files = os.listdir(package)

    for file in files:
        if not file.startswith("__"):
            name, ext = os.path.splitext(file)
            modules.append("." + name)

    return modules


if __name__ == '__main__':
    package = "clazz"
    modules = get_modules(package)

    # 将包下的所有模块,逐个导入,并调用其中的函数
    for module in modules:
        module = importlib.import_module(module, package)
        
        for attr in dir(module):
            if not attr.startswith("__"):
                func = getattr(module, attr)
                func()

    """
    show A
    show B
    """

可以看到,我在只知道包名的情况下,成功获取了包下所有模块,和模块中所有的方法,并成功调用

注意,相对导入的时候需要在模块名前面加.

but!!!,

Python推荐使用pkgutil.iter_modules(path=None, prefix='')

import pkgutil, clazz

for filefiner, name, ispkg in pkgutil.iter_modules(clazz.__path__, clazz.__name__ + "."):
    print("{0} name: {1:12}, is_sub_package: {2}".format(filefiner, name, ispkg))

"""
FileFinder('/Users/qmp/myproject/mydemo/demo/allclass/clazz') name: clazz.a     , is_sub_package: False
FileFinder('/Users/qmp/myproject/mydemo/demo/allclass/clazz') name: clazz.b     , is_sub_package: False
"""

函数 iter_modules() 和 walk_packages() 的区别在于:后者会迭代所有深度的子包

import pkgutil, test

for _, name, ispkg in pkgutil.iter_modules(test.__path__, test.__name__ + "."):
	print "name: {0:12}, is_sub_package: {1}".format(name, ispkg)

"""
name: test.a , is_sub_package: True
name: test.add , is_sub_package: False
name: test.b , is_sub_package: True
name: test.user , is_sub_package: False
"""


# 需要加第二个参数 prefix
for _, name, ispkg in pkgutil.walk_packages(test.__path__, test.__name__ + "."):
    print "name: {0:12}, is_sub_package: {1}".format(name, ispkg)
"""
name: test.a , is_sub_package: True
name: test.a.sub , is_sub_package: False
name: test.add , is_sub_package: False
name: test.b , is_sub_package: True
name: test.b.sub , is_sub_package: False
name: test.user , is_sub_package: False
"""

pkgutil.get_data() 可读取包内任何文件内容:

pkgutil.get_data("test", "add.py")

配合动态导包模块一起使用,实现模块的热插拔技术:

当使用import导入Python模块的时候,默认调用的是__import__()函数。直接使用该函数的情况很少见,一般用于动态加载模块。

__import__(name, globals, locals, fromlist, level)只有name是必选参数,其他都是可选参数,一般情况下直接使用name参数即可。

fromlist指明需要导入的子模块名,level指定导入方式(相对导入或者绝对导入, 默认两者都支持)。

当模块名为package.module时,而且fromlist参数为空时,函数返回顶层的模块,也就是package模块。如果fromlist=[module],则返回module

所以,下面语句返回的结果是一样的:

 
  1. spam = __import__('spam', globals(), locals(), [], -1)

  2. spam = __import__('spam.ham', globals(), locals(), [], -1)

而下面指定了fromlist,就可以获取到子模块。

 
  1. _temp = __import__('spam.ham', globals(), locals(), ['eggs', 'sausage'], -1)

  2. eggs = _temp.eggs

  3. saus = _temp.sausage

如果像直接通过名字导入模块,也可以使用importlib模块的import_module函数。

官方推荐使用import_module模块实现导包

 

可以使用__import__函数实现模块的延迟导入:

  1. class LazyImport:

  2. def __init__(self, module_name):

  3. self.module_name = module_name

  4. self.module = None

  5. def __getattr__(self, name):

  6. if self.module is None:

  7. self.module = __import__(self.module_name)

  8. return getattr(self.module, name)

  9. string = LazyImport("string")

  10. print string.lowercase

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1024小神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值