列出属于 python 包的所有模块?
有没有一种简单的方法来查找 python 包中的所有模块?我发现这个旧讨论,其中并不是真正决定性的,但在我推出基于 os.listdir() 的自己的解决方案之前,我希望得到一个明确的答案。
Is there a straightforward way to find all the modules that are part of a python package? I've found this old discussion, which is not really conclusive, but I'd love to have a definite answer before I roll out my own solution based on os.listdir().
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
是的,您想要基于 pkgutil 或类似的东西 - 这样您就可以同等对待所有包,无论它们是在 Eggs 还是 zips 中(其中 os.listdir 没有帮助)。
如何导入它们呢?您可以像平常一样使用
__import__
:Yes, you want something based on
pkgutil
or similar -- this way you can treat all packages alike regardless if they are in eggs or zips or so (where os.listdir won't help).How to import them too? You can just use
__import__
as normal:适合这项工作的工具是 pkgutil.walk_packages。
要列出系统上的所有模块:
请注意 walk_packages 导入所有子包,但不导入子模块。
如果您希望列出某个包的所有子模块,那么您可以使用类似这样的内容:
iter_modules 仅列出一层深度的模块。
walk_packages 获取所有子模块。
例如,对于 scipy,walk_packages 返回,
而 iter_modules 仅返回
pkgutil 上的文档 (http://docs.python. org/library/pkgutil.html)
没有列出中定义的所有有趣的函数
/usr/lib/python2.6/pkgutil.py。
也许这意味着这些功能不是“公共”界面的一部分并且可能会发生变化。
然而,至少从 Python 2.6 开始(也许更早的版本?)
pkgutil 附带了一个 walk_packages 方法,它递归地遍历所有
可用模块。
The right tool for this job is pkgutil.walk_packages.
To list all the modules on your system:
Be aware that walk_packages imports all subpackages, but not submodules.
If you wish to list all submodules of a certain package then you can use something like this:
iter_modules only lists the modules which are one-level deep.
walk_packages gets all the submodules.
In the case of scipy, for example, walk_packages returns
while iter_modules only returns
The documentation on pkgutil (http://docs.python.org/library/pkgutil.html)
does not list all the interesting functions defined in
/usr/lib/python2.6/pkgutil.py.
Perhaps this means the functions are not part of the "public" interface and are subject to change.
However, at least as of Python 2.6 (and perhaps earlier versions?)
pkgutil comes with a walk_packages method which recursively walks through all the
modules available.
这对我有用:
This works for me:
感谢之前的所有答案,我刚刚将它们全部合并到一个函数中,该函数可以轻松地用于检索子模块:
然后您可以像这样调用它:
Thanks to all previous answers, I've just merged them all into one function, which can be easily used to retrieve submodules:
Then you can just call it like:
我正在寻找一种方法来重新加载我正在包中实时编辑的所有子模块。它是上面答案/评论的组合,所以我决定将其作为答案而不是评论发布在这里。
I was looking for a way to reload all submodules that I'm editing live in my package. It is a combination of the answers/comments above, so I've decided to post it here as an answer rather than a comment.
如果您不仅对列出模块名称感兴趣,而且还想获取对
module
对象的引用,那么这个答案适合您:要列出模块,请使用
pkgutil.iter_modules
如果您只需要 的直接子级模块,或pkgutil.walk_packages
如果您需要模块的所有后代。两者都返回ModuleInfo
元组。要导入模块,现有答案中有各种建议,其中大多数都不是很好的选择:
__import__
如果您导入顶级模块__import__('foo')
则有效,但__import__('foo.bar')< /code> 还将返回
foo
模块,而不是foo.bar
!您可以解决此限制,但很麻烦。MetaPathFinder.find_module
:自 Python 3.4 起已弃用,并在 3.12 中删除MetaPathFinder.find_spec
替代了find_module
,可以通过访问ModuleInfo.module_finder
属性来使用它,但是有点冗长:我的首选方法是使用
importlib.import_module
与pkgutil.iter_modules
结合使用:关于此解决方案的一些注意事项:
pkgutil.iter_modules
替换为pkgutil.walk_packages
如果需要,importlib.import_module
返回路径指定的模块,而不是路径根部的模块,例如__import__
f"{module.__name__} .{module_info.name}"
我们确保所有模块都通过绝对路径引用(如果之前已导入父模块,则可以使用更短的路径加载模块,但是如果您想过滤,这可能会导致问题或比较模块)In case you are not only interested in listing module names, but you also want to get a reference to the
module
objects, this answer is for you:To list modules, use either
pkgutil.iter_modules
if you need just the direct children of a module, orpkgutil.walk_packages
if you need all descendants of a module. Both returnModuleInfo
tuples.To import modules, there are various suggestions in the existing answers, most of which are not great choices:
__import__
works if you import a top level module__import__('foo')
, but__import__('foo.bar')
will also return thefoo
module, notfoo.bar
! You can work around this restriction, but it is cumbersome.MetaPathFinder.find_module
: has been deprecated since Python 3.4 and was removed in 3.12MetaPathFinder.find_spec
replacesfind_module
, you can use it by accessing theModuleInfo.module_finder
attribute, but it's a bit verbose:My preferred method is to use
importlib.import_module
in combination withpkgutil.iter_modules
:a few notes on this solution:
pkgutil.iter_modules
withpkgutil.walk_packages
if neededimportlib.import_module
returns the module specified by the path, not the module at the root of the path, like__import__
f"{module.__name__}.{module_info.name}"
we make sure that all modules are referenced by an absolute path (modules can be loaded with shorter paths if the parent module has been imported before, but this can cause issues if you want to filter or compare modules)这是我突然想到的一种方法:
它肯定可以得到清理和改进。
编辑:这是一个稍微好一点的版本:
注意:这还会找到不一定位于包的子目录中的模块(如果它们被拉入包的子目录中)
__init__.py
文件,因此这取决于您所说的包的“一部分”的含义。Here's one way, off the top of my head:
It could certainly be cleaned up and improved.
EDIT: Here's a slightly nicer version:
NOTE: This will also find modules that might not necessarily be located in a subdirectory of the package, if they're pulled in in its
__init__.py
file, so it depends on what you mean by "part of" a package.