importlib.metadata – Accessing package metadata

New in version 3.8.

Changed in version 3.10:importlib.metadata is no longer provisional.

Source code:Lib/importlib/metadata/__init__.py

importlib.metadata is a library that provides access tothe metadata of an installedDistribution Package,such as its entry pointsor its top-level names (Import Packages, modules, if any).Built in part on Python’s import system, this libraryintends to replace similar functionality in theentry pointAPI andmetadata API ofpkg_resources. Along withimportlib.resources,this package can eliminate the need to use the older and less efficientpkg_resources package.

importlib.metadata operates on third-partydistribution packagesinstalled into Python’ssite-packages directory via tools such aspip.Specifically, it works with distributions with discoverabledist-info oregg-info directories,and metadata defined by theCore metadata specifications.

Important

These arenot necessarily equivalent to or correspond 1:1 withthe top-levelimport package namesthat can be imported inside Python code.Onedistribution package can contain multipleimport packages(and single modules),and one top-levelimport packagemay map to multipledistribution packagesif it is a namespace package.You can usepackage_distributions()to get a mapping between them.

By default, distribution metadata can live on the file systemor in zip archives onsys.path. Through an extension mechanism, the metadata can live almostanywhere.

See also

https://importlib-metadata.readthedocs.io/

The documentation forimportlib_metadata, which supplies abackport ofimportlib.metadata.This includes anAPI referencefor this module’s classes and functions,as well as amigration guidefor existing users ofpkg_resources.

Overview

Let’s say you wanted to get the version string for aDistribution Package you’ve installedusingpip. We start by creating a virtual environment and installingsomething into it:

$python-mvenvexample$sourceexample/bin/activate(example)$python-mpipinstallwheel

You can get the version string forwheel by running the following:

(example) $ python>>>fromimportlib.metadataimportversion>>>version('wheel')'0.32.3'

You can also get a collection of entry points selectable by properties of the EntryPoint (typically ‘group’ or ‘name’), such asconsole_scripts,distutils.commands and others. Each group contains acollection ofEntryPoint objects.

You can get themetadata for a distribution:

>>>list(metadata('wheel'))['Metadata-Version', 'Name', 'Version', 'Summary', 'Home-page', 'Author', 'Author-email', 'Maintainer', 'Maintainer-email', 'License', 'Project-URL', 'Project-URL', 'Project-URL', 'Keywords', 'Platform', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Requires-Python', 'Provides-Extra', 'Requires-Dist', 'Requires-Dist']

You can also get adistribution’s version number, list itsconstituent files, and get a list of the distribution’sDistribution requirements.

Functional API

This package provides the following functionality via its public API.

Entry points

Theentry_points() function returns a collection of entry points.Entry points are represented byEntryPoint instances;eachEntryPoint has a.name,.group, and.value attributes anda.load() method to resolve the value. There are also.module,.attr, and.extras attributes for getting the components of the.value attribute.

Query all entry points:

>>>eps=entry_points()

Theentry_points() function returns anEntryPoints object,a collection of allEntryPoint objects withnames andgroupsattributes for convenience:

>>>sorted(eps.groups)['console_scripts', 'distutils.commands', 'distutils.setup_keywords', 'egg_info.writers', 'setuptools.installation']

EntryPoints has aselect method to select entry pointsmatching specific properties. Select entry points in theconsole_scripts group:

>>>scripts=eps.select(group='console_scripts')

Equivalently, sinceentry_points passes keyword argumentsthrough to select:

>>>scripts=entry_points(group='console_scripts')

Pick out a specific script named “wheel” (found in the wheel project):

>>>'wheel'inscripts.namesTrue>>>wheel=scripts['wheel']

Equivalently, query for that entry point during selection:

>>>(wheel,)=entry_points(group='console_scripts',name='wheel')>>>(wheel,)=entry_points().select(group='console_scripts',name='wheel')

Inspect the resolved entry point:

>>>wheelEntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts')>>>wheel.module'wheel.cli'>>>wheel.attr'main'>>>wheel.extras[]>>>main=wheel.load()>>>main<function main at 0x103528488>

Thegroup andname are arbitrary values defined by the package authorand usually a client will wish to resolve all entry points for a particulargroup. Readthe setuptools docsfor more information on entry points, their definition, and usage.

Compatibility Note

The “selectable” entry points were introduced inimportlib_metadata3.6 and Python 3.10. Prior to those changes,entry_points acceptedno parameters and always returned a dictionary of entry points, keyedby group. For compatibility, if no parameters are passed to entry_points,aSelectableGroups object is returned, implementing that dictinterface. In the future, callingentry_points with no parameterswill return anEntryPoints object. Users should rely on the selectioninterface to retrieve entry points by group.

Distribution metadata

EveryDistribution Package includes some metadata,which you can extract using themetadata() function:

>>>wheel_metadata=metadata('wheel')

The keys of the returned data structure, aPackageMetadata,name the metadata keywords, andthe values are returned unparsed from the distribution metadata:

>>>wheel_metadata['Requires-Python']'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'

PackageMetadata also presents ajson attribute that returnsall the metadata in a JSON-compatible form perPEP 566:

>>>wheel_metadata.json['requires_python']'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'

Note

The actual type of the object returned bymetadata() is animplementation detail and should be accessed only through the interfacedescribed by thePackageMetadata protocol.

Changed in version 3.10:TheDescription is now included in the metadata when presentedthrough the payload. Line continuation characters have been removed.

Thejson attribute was added.

Distribution versions

Theversion() function is the quickest way to get aDistribution Package’s versionnumber, as a string:

>>>version('wheel')'0.32.3'

Distribution files

You can also get the full set of files contained within a distribution. Thefiles() function takes aDistribution Package nameand returns all of thefiles installed by this distribution. Each file object returned is aPackagePath, apathlib.PurePath derived object with additionaldist,size, andhash properties as indicated by the metadata. For example:

>>>util=[pforpinfiles('wheel')if'util.py'instr(p)][0]>>>utilPackagePath('wheel/util.py')>>>util.size859>>>util.dist<importlib.metadata._hooks.PathDistribution object at 0x101e0cef0>>>>util.hash<FileHash mode: sha256 value: bYkw5oMccfazVCoYQwKkkemoVyMAFoR34mmKBx8R1NI>

Once you have the file, you can also read its contents:

>>>print(util.read_text())import base64import sys...def as_bytes(s):    if isinstance(s, text_type):        return s.encode('utf-8')    return s

You can also use thelocate method to get a the absolute path to thefile:

>>>util.locate()PosixPath('/home/gustav/example/lib/site-packages/wheel/util.py')

In the case where the metadata file listing files(RECORD or SOURCES.txt) is missing,files() willreturnNone. The caller may wish to wrap calls tofiles() inalways_iterableor otherwise guard against this condition if the targetdistribution is not known to have the metadata present.

Distribution requirements

To get the full set of requirements for aDistribution Package,use therequires()function:

>>>requires('wheel')["pytest (>=3.0.0) ; extra == 'test'", "pytest-cov ; extra == 'test'"]

Mapping import to distribution packages

A convenience method to resolve theDistribution Packagename (or names, in the case of a namespace package)that provide each importable top-levelPython module orImport Package:

>>>packages_distributions(){'importlib_metadata': ['importlib-metadata'], 'yaml': ['PyYAML'], 'jaraco': ['jaraco.classes', 'jaraco.functools'], ...}

New in version 3.10.

Distributions

While the above API is the most common and convenient usage, you can get allof that information from theDistribution class. ADistribution is anabstract object that represents the metadata fora PythonDistribution Package. You canget theDistribution instance:

>>>fromimportlib.metadataimportdistribution>>>dist=distribution('wheel')

Thus, an alternative way to get the version number is through theDistribution instance:

>>>dist.version'0.32.3'

There are all kinds of additional metadata available on theDistributioninstance:

>>>dist.metadata['Requires-Python']'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'>>>dist.metadata['License']'MIT'

The full set of available metadata is not described here.See theCore metadata specifications for additional details.

Distribution Discovery

By default, this package provides built-in support for discovery of metadatafor file system and zip fileDistribution Packages.This metadata finder search defaults tosys.path, but varies slightly in how it interprets those values from how other import machinery does. In particular:

  • importlib.metadata does not honorbytes objects onsys.path.

  • importlib.metadata will incidentally honorpathlib.Path objects onsys.path even though such values will be ignored for imports.

Extending the search algorithm

BecauseDistribution Package metadatais not available throughsys.path searches, orpackage loaders directly,the metadata for a distribution is found through importsystemfinders. To find a distribution package’s metadata,importlib.metadata queries the list ofmeta path finders onsys.meta_path.

By defaultimportlib.metadata installs a finder for distribution packagesfound on the file system.This finder doesn’t actually find anydistributions,but it can find their metadata.

The abstract classimportlib.abc.MetaPathFinder defines theinterface expected of finders by Python’s import system.importlib.metadata extends this protocol by looking for an optionalfind_distributions callable on the finders fromsys.meta_path and presents this extended interface as theDistributionFinder abstract base class, which defines this abstractmethod:

@abc.abstractmethoddeffind_distributions(context=DistributionFinder.Context()):"""Return an iterable of all Distribution instances capable of    loading the metadata for packages for the indicated ``context``.    """

TheDistributionFinder.Context object provides.path and.nameproperties indicating the path to search and name to match and maysupply other relevant context.

What this means in practice is that to support finding distribution packagemetadata in locations other than the file system, subclassDistribution and implement the abstract methods. Then froma custom finder, return instances of this derivedDistribution in thefind_distributions() method.