是否有一种标准的方法来列出包中的Python模块的名称?

DNS*_*DNS 87 python module package

是否有直接的方法列出包中所有模块的名称,而不使用__all__

例如,给定此包:

/testpkg
/testpkg/__init__.py
/testpkg/modulea.py
/testpkg/moduleb.py
Run Code Online (Sandbox Code Playgroud)

我想知道是否有标准或内置方式来做这样的事情:

>>> package_contents("testpkg")
['modulea', 'moduleb']
Run Code Online (Sandbox Code Playgroud)

手动方法是遍历模块搜索路径以查找包的目录.然后可以列出该目录中的所有文件,过滤掉唯一命名的py/pyc/pyo文件,剥离扩展名,然后返回该列表.但对于模块导入机制已在内部进行的操作,这似乎是相当多的工作.该功能是否暴露在任何地方

小智 179

使用python2.3及更高版本,您还可以使用该pkgutil模块:

>>> import pkgutil
>>> [name for _, name, _ in pkgutil.iter_modules(['testpkg'])]
['modulea', 'moduleb']
Run Code Online (Sandbox Code Playgroud)

编辑:请注意,该参数不是模块列表,而是路径列表,因此您可能希望执行以下操作:

>>> import os.path, pkgutil
>>> import testpkg
>>> pkgpath = os.path.dirname(testpkg.__file__)
>>> print [name for _, name, _ in pkgutil.iter_modules([pkgpath])]
Run Code Online (Sandbox Code Playgroud)

  • 这令人不安地没有记录,但似乎是最正确的方法.希望你不介意我添加了说明. (15认同)
  • `pkgutil`在[python2.3实际上]中存在(http://docs.python.org/library/pkgutil.html).此外,虽然`pkgutil.iter_modules()`不会递归地工作,但也有一个`pkgutil.walk_packages()`,_will_ recurse.谢谢你指向这个包的指针. (12认同)
  • 我无法确认 `pkgutil.walk_packages()` 递归,它给我提供与 `pkgutil.iter_modules()` 相同的输出,所以我认为答案不完整。 (4认同)
  • 如果有人关心的话,这在 python 3.8 中也可以完美运行(只是说原来的帖子很旧) (4认同)
  • 我认为你根本不需要在这里使用 os 。你应该能够这样做: `[name for _, name, _ in pkgutil.iter_modules(testpkg.__path__)]` (2认同)

Tri*_*ych 26

import module
help(module)
Run Code Online (Sandbox Code Playgroud)

  • 尽管help确实在帮助文本的底部列出了软件包的内容,但问题更多的是如何做到这一点:f(package_name)=> [“” module1_name“,” module2_name“]。我想我可以解析help返回的字符串,但是这似乎比列出目录更为复杂。 (2认同)
  • @DNS:`help()`打印内容,它不返回字符串。 (2认同)
  • 我同意这是一种迂回的方式,但它让我陷入了困境,想看看“help()”是如何工作的。不管怎样,内置的 pydoc 模块可以帮助吐出 help() 分页的字符串: import pydoc; pydoc.render_doc('mypackage')`。 (2认同)

cdl*_*ary 19

也许这会做你想要的?

import imp
import os
MODULE_EXTENSIONS = ('.py', '.pyc', '.pyo')

def package_contents(package_name):
    file, pathname, description = imp.find_module(package_name)
    if file:
        raise ImportError('Not a package: %r', package_name)
    # Use a set because some may be both source and compiled.
    return set([os.path.splitext(module)[0]
        for module in os.listdir(pathname)
        if module.endswith(MODULE_EXTENSIONS)])
Run Code Online (Sandbox Code Playgroud)

  • 您应该使用`imp.get_suffixes()`而不是手写列表. (5认同)
  • 我不同意 - 你可以直接导入__init__,为什么特殊情况呢?确实不足以打破规则.;-) (3认同)
  • 另请注意,这不适用于像`xml.sax`这样的子包 (3认同)

sie*_*z0r 7

不知道我是否忽略了什么,或者答案是否已过时但是;

如user815423426所述,这仅适用于活动对象,并且列出的模块仅是之前导入的模块.

使用inspect查看包中的模块似乎非常简单:

>>> import inspect, testpkg
>>> inspect.getmembers(testpkg, inspect.ismodule)
['modulea', 'moduleb']
Run Code Online (Sandbox Code Playgroud)

  • @ user815423426你是绝对正确的;-)好像我在忽略一些东西. (3认同)