Gibt es eine standardisierte Art und Weise Namen von Python-Modulen in einem Paket zur Liste?
Frage
Gibt es eine einfache Möglichkeit, die Namen aller Module in einem Paket zur Liste, ohne __all__
mit?
Zum Beispiel gegeben, dieses Paket:
/testpkg
/testpkg/__init__.py
/testpkg/modulea.py
/testpkg/moduleb.py
Ich frage mich, ob es eine Standard- oder integrierte Möglichkeit ist, so etwas zu tun:
>>> package_contents("testpkg")
['modulea', 'moduleb']
Der manuelle Ansatz wäre es, durch die Modul-Suchpfade, um iterieren das Paket des Verzeichnis zu finden. Man könnte dann eine Liste aller Dateien in diesem Verzeichnis, herauszufiltern, die mit eindeutigem Namen py / pyc / Pyo Dateien, die Erweiterungen abzustreifen, und diese Liste zurückzukehren. Aber dies scheint wie eine Menge Arbeit für etwas das Modul Import-Mechanismus bereits intern tut. Ist diese Funktionalität ausgesetzt überall?
Lösung
Vielleicht wird dies tun, was Sie suchen?
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)])
Andere Tipps
python2.3 Mit und über , können Sie auch den pkgutil
Modul verwenden:
>>> import pkgutil
>>> [name for _, name, _ in pkgutil.iter_modules(['testpkg'])]
['modulea', 'moduleb']
EDIT: Beachten Sie, dass der Parameter nicht eine Liste der Module, sondern eine Liste von Pfaden, so dass Sie so etwas wie dies tun mögen:
>>> 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)
Ich weiß nicht, ob ich etwas mit Blick auf bin, oder wenn die Antworten sind nur veraltet, sondern;
Wie user815423426 erklärte dies funktioniert nur für Live-Objekte und die aufgeführten Module sind nur Module, die vor importiert wurden.
Module in einem Paket Listing scheint einfach inspiziert :
>>> import inspect, testpkg
>>> inspect.getmembers(testpkg, inspect.ismodule)
['modulea', 'moduleb']
Dies ist eine rekursive Version, die mit Python funktioniert 3.6 und höher:
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
Diese sollten alle Module:
help("modules")
Wenn Sie möchten, dass eine inforamtion über Ihr Paket außerhalb des Python-Code (von einer Eingabeaufforderung) anzuzeigen pydoc für sie verwenden kann.
# 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>
Sie werden das gleiche Ergebnis wie pydoc haben, aber innerhalb des Dolmetschers mit Hilfe
>>> import <my package>
>>> help(<my package>)
Basierend auf cdleary dem Beispiel, hier ist eine rekursive Version Listing Pfad für alle Submodule:
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)
Druck dir (Modul)
def package_contents(package_name):
package = __import__(package_name)
return [module_name for module_name in dir(package) if not module_name.startswith("__")]