0
点赞
收藏
分享

微信扫一扫

Python编程:pkgutil获取包里面的所有模块列表


准备工作

环境: python 3.6

文件结构

├── clazz
│ ├── __init__.py
│ ├── a.py
│ └── b.py
└── main.py

​a.py​​ 的代码

def show():
print("show A")

​b.py​​ 的代码

def show():
print("show B")

测试开始

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")


参考

  1. ​​Python 学习笔记 - 模块​​




举报

相关推荐

0 条评论