Existe-t-il un moyen simple de répertorier les noms de tous les modules d’un package sans utiliser __all__
?
Par exemple, étant donné ce paquet:
/testpkg
/testpkg/__init__.py
/testpkg/modulea.py
/testpkg/moduleb.py
Je me demande s'il existe une manière standard ou intégrée de faire quelque chose comme ceci:
>>> package_contents("testpkg")
['modulea', 'moduleb']
L'approche manuelle consisterait à parcourir les chemins de recherche du module afin de trouver le répertoire du paquet. Vous pouvez ensuite répertorier tous les fichiers de ce répertoire, filtrer les fichiers py/pyc/pyo, nommés de manière unique, effacer les extensions et renvoyer cette liste. Mais cela semble être un travail considérable pour quelque chose que le mécanisme d’importation de module fait déjà en interne. Cette fonctionnalité est-elle exposée quelque part?
Peut-être que cela fera ce que vous cherchez?
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)])
En utilisant python2.3 et supérieur , vous pouvez également utiliser le module pkgutil
:
>>> import pkgutil
>>> [name for _, name, _ in pkgutil.iter_modules(['testpkg'])]
['modulea', 'moduleb']
EDIT: Notez que le paramètre n'est pas une liste de modules, mais une liste de chemins. Vous voudrez peut-être faire quelque chose comme ceci:
>>> import os.path, pkgutil
>>> import testpkg
>>> pkgpath = os.path.dirname(testpkg.__file__)
>>> print [name for _, name, _ in pkgutil.iter_modules([pkgpath])]
import module
help(module)
Je ne sais pas si je néglige quelque chose ou si les réponses sont simplement obsolètes, mais
Comme indiqué par l'utilisateur815423426, cela ne fonctionne que pour les objets dynamiques et les modules répertoriés ne sont que des modules importés auparavant.
La liste des modules dans un paquet semble très facile avec inspect :
>>> import inspect, testpkg
>>> inspect.getmembers(testpkg, inspect.ismodule)
['modulea', 'moduleb']
Ceci est une version récursive qui fonctionne avec Python 3.6 et supérieur:
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
Si vous souhaitez afficher une information sur votre paquet en dehors du code python (à partir d'une invite de commande), vous pouvez utiliser pydoc pour cela.
# 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>
Vous obtiendrez le même résultat que pydoc mais à l’intérieur de l’interprète utilisant l’aide
>>> import <my package>
>>> help(<my package>)
D'après l'exemple de cdleary, voici un chemin de liste de version récursif pour tous les sous-modules:
import imp, os
def iter_submodules(package):
file, pathname, description = imp.find_module('isc_datasources')
for dirpath, _, filenames in os.walk(pathname):
for filename in filenames:
if os.path.splitext(filename)[1] == ".py":
yield os.path.join(dirpath, filename)
Cela devrait lister les modules:
help("modules")