如何无需执行from modulename import *查看Python模块的所有扩展?
from modulename import *) 嘿,我来给你捋捋怎么解决这个问题——你是不是发现用dir()查看模块的点操作选项时,好多子模块都藏着不显示,非得显式导入之后才会出现在列表里?就像你用sklearn的时候,一开始dir(sklearn)看不到tree,得import sklearn.tree之后才会出现在结果里对吧?
其实这是因为Python的包采用懒加载机制:默认不会自动导入所有子模块,只有当你显式导入时,才会把子模块添加到包的命名空间中,这样能减少程序启动时间和内存占用。下面给你几个不用from modulename import *就能查看所有子模块的方法:
方法1:用pkgutil模块(最靠谱的官方方式)
pkgutil是Python标准库中专门用来处理包和模块的工具,它能递归遍历包的所有子模块,还能区分普通模块和子包:
import pkgutil import sklearn # 遍历sklearn的所有子模块,prefix参数用来添加父模块前缀 for importer, modname, ispkg in pkgutil.walk_packages(sklearn.__path__, prefix='sklearn.'): print(modname)
运行后会输出所有可导入的子模块,比如sklearn.tree、sklearn.ensemble.RandomForestClassifier这类嵌套模块,而且自动过滤掉不可导入的文件。
方法2:手动遍历包的目录(适合简单场景)
如果不想用标准库工具,也可以直接通过模块的__path__属性获取包的目录路径,手动遍历文件和子目录:
import os import sklearn # 遍历sklearn包的所有路径(有些包可能有多个路径) for pkg_path in sklearn.__path__: for item in os.listdir(pkg_path): full_path = os.path.join(pkg_path, item) # 筛选子包(目录)或.py文件 if os.path.isdir(full_path) or item.endswith('.py'): # 提取模块名(去掉.py后缀) module_name = item.split('.')[0] # 排除私有模块(以_开头的) if not module_name.startswith('_'): print(module_name)
不过这种方法有局限性:会把一些不是可导入模块的文件(比如测试文件、配置文件)也列出来,而且无法递归显示嵌套的子模块,需要自己额外处理递归逻辑。
方法3:查看__all__属性(仅供参考)
有些模块会在__init__.py里定义__all__列表,用来声明from modulename import *时要导入的内容,但很多模块的__all__并不会包含所有子模块(比如sklearn的__all__就没包含tree),所以这个方法只能作为补充:
import sklearn print(sklearn.__all__)
总结一下:如果要准确、全面地查看模块的所有扩展,优先用pkgutil.walk_packages;简单场景下可以手动遍历目录;__all__只能参考,不能依赖。
内容的提问来源于stack exchange,提问作者moishinetzer

