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

时间:2009-01-28 15:11:33

标签: python module package

是否有一种简单的方法可以列出包中所有模块的名称,而不使用__all__

例如,给定此包:

/testpkg
/testpkg/__init__.py
/testpkg/modulea.py
/testpkg/moduleb.py

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

>>> package_contents("testpkg")
['modulea', 'moduleb']

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

10 个答案:

答案 0 :(得分:172)

使用python2.3 and above,您还可以使用pkgutil模块:

>>> import pkgutil
>>> [name for _, name, _ in pkgutil.iter_modules(['testpkg'])]
['modulea', 'moduleb']

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

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

答案 1 :(得分:25)

import module
help(module)

答案 2 :(得分:18)

也许这会做你想要的?

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

答案 3 :(得分:7)

不知道我是否忽略了某些东西,或者答案是否过时但是;

如user815423426所述,这仅适用于实时对象,列出的模块只是之前导入的模块。

使用inspect

,在包中列出模块似乎非常简单
>>> import inspect, testpkg
>>> inspect.getmembers(testpkg, inspect.ismodule)
['modulea', 'moduleb']

答案 4 :(得分:2)

这是一个适用于python 3.6及更高版本的递归版本:

import importlib.util
from pathlib import Path
import os
MODULE_EXTENSIONS = '.py'

def package_contents(package_name):
    spec = importlib.util.find_spec(package_name)
    if spec is None:
        return set()

    pathname = Path(spec.origin).parent
    ret = set()
    with os.scandir(pathname) as entries:
        for entry in entries:
            if entry.name.startswith('__'):
                continue
            current = '.'.join((package_name, entry.name.partition('.')[0]))
            if entry.is_file():
                if entry.name.endswith(MODULE_EXTENSIONS):
                    ret.add(current)
            elif entry.is_dir():
                ret.add(current)
                ret |= package_contents(current)


    return ret

答案 5 :(得分:0)

基于cdleary的例子,这里是所有子模块的递归版本列表路径:

import imp, os

def iter_submodules(package):
    file, pathname, description = imp.find_module(package)
    for dirpath, _, filenames in os.walk(pathname):
        for  filename in filenames:
            if os.path.splitext(filename)[1] == ".py":
                yield os.path.join(dirpath, filename)

答案 6 :(得分:0)

这应该列出模块:

help("modules")

答案 7 :(得分:0)

如果您想在python代码之外(从命令提示符下)查看有关软件包的信息,则可以使用pydoc。

# get a full list of packages that you have installed on you machine
$ python -m pydoc modules

# get information about a specific package
$ python -m pydoc <your package>

您将获得与pydoc相同的结果,但在解释器中使用help

>>> import <my package>
>>> help(<my package>)

答案 8 :(得分:-2)

print dir(module)

答案 9 :(得分:-2)

def package_contents(package_name):
  package = __import__(package_name)
  return [module_name for module_name in dir(package) if not module_name.startswith("__")]