This module provides functions to manipulate packages, as well as the necessary functions to provide support for the “Importer Protocol” as described in PEP 302 and for working with the database of installed Python distributions which is specified in PEP 376. In addition to the functions required in PEP 376, back support for older .egg and .egg-info distributions is provided as well. These distributions are represented by the class EggInfoDistribution and most functions provide an extra argument use_egg_info which indicates if they should consider these old styled distributions. This document details first the functions and classes available and then presents several use cases.
Extend the search path for the modules which comprise a package. Intended use is to place the following code in a package’s __init__.py:
from pkgutil import extend_path __path__ = extend_path(__path__, __name__)
This will add to the package’s __path__ all subdirectories of directories on sys.path named after the package. This is useful if one wants to distribute different parts of a single logical package as multiple directories.
It also looks for *.pkg files beginning where * matches the name argument. This feature is similar to *.pth files (see the site module for more information), except that it doesn’t special-case lines starting with import. A *.pkg file is trusted at face value: apart from checking for duplicates, all entries found in a *.pkg file are added to the path, regardless of whether they exist on the filesystem. (This is a feature.)
If the input path is not a list (as is the case for frozen packages) it is returned unchanged. The input path is not modified; an extended copy is returned. Items are only appended to the copy at the end.
It is assumed that sys.path is a sequence. Items of sys.path that are not strings referring to existing directories are ignored. Unicode items on sys.path that cause errors when used as filenames may cause this function to raise an exception (in line with os.path.isdir() behavior).
Get a resource from a package.
This is a wrapper for the PEP 302 loader get_data() API. The package argument should be the name of a package, in standard module format (foo.bar). The resource argument should be in the form of a relative filename, using / as the path separator. The parent directory name .. is not allowed, and nor is a rooted name (starting with a /).
The function returns a binary string that is the contents of the specified resource.
For packages located in the filesystem, which have already been imported, this is the rough equivalent of:
d = os.path.dirname(sys.modules[package].__file__) data = open(os.path.join(d, resource), 'rb').read()
For performance purposes, the list of distributions is being internally cached. It is enabled by default, but you can turn it off or clear it using enable_cache(), disable_cache() and clear_cache().
Given a path to a .dist-info distribution, we shall print out all information that can be obtained using functions provided in this module:
from distutils2._backport import pkgutil import sys path = raw_input() # read the path from the keyboard # first create the Distribution instance try: dist = pkgutil.Distribution(path) except IOError: print('No such distribution') sys.exit(1) print('Information about %s' % dist.name) print('Files') print('=====') for (path, md5, size) in dist.get_installed_files(): print('* Path: %s' % path) print(' Hash %s, Size: %s bytes' % (md5, size)) print('Metadata') print('========') for key, value in dist.metadata.items(): print('%20s: %s' % (key, value)) print('Extra') print('=====') if dist.requested: print('* It was installed by user request') else: print('* It was installed as a dependency')
If we save the script above as print_info.py and we are intested in the distribution located at /home/josip/dev/distutils2/src/distutils2/_backport/tests/fake_dists/choxie-22.214.171.124 then by typing in the console:
$ echo /home/josip/dev/distutils2/src/distutils2/_backport/tests/fake_dists/choxie-126.96.36.199.dist-info | python print_info.py
we get the following output:
Information about choxie Files ===== * Path: ../home/josip/dev/distutils2/src/distutils2/_backport/tests/fake_dists/choxie-188.8.131.52/truffles.py Hash 5e052db6a478d06bad9ae033e6bc08af, Size: 111 bytes * Path: ../home/josip/dev/distutils2/src/distutils2/_backport/tests/fake_dists/choxie-184.108.40.206/choxie/chocolate.py Hash ac56bf496d8d1d26f866235b95f31030, Size: 214 bytes * Path: ../home/josip/dev/distutils2/src/distutils2/_backport/tests/fake_dists/choxie-220.127.116.11/choxie/__init__.py Hash 416aab08dfa846f473129e89a7625bbc, Size: 25 bytes * Path: ../home/josip/dev/distutils2/src/distutils2/_backport/tests/fake_dists/choxie-18.104.22.168.dist-info/INSTALLER Hash d41d8cd98f00b204e9800998ecf8427e, Size: 0 bytes * Path: ../home/josip/dev/distutils2/src/distutils2/_backport/tests/fake_dists/choxie-22.214.171.124.dist-info/METADATA Hash 696a209967fef3c8b8f5a7bb10386385, Size: 225 bytes * Path: ../home/josip/dev/distutils2/src/distutils2/_backport/tests/fake_dists/choxie-126.96.36.199.dist-info/REQUESTED Hash d41d8cd98f00b204e9800998ecf8427e, Size: 0 bytes * Path: ../home/josip/dev/distutils2/src/distutils2/_backport/tests/fake_dists/choxie-188.8.131.52.dist-info/RECORD Hash None, Size: None bytes Metadata ======== Metadata-Version: 1.2 Name: choxie Version: 184.108.40.206 Platform:  Supported-Platform: UNKNOWN Summary: Chocolate with a kick! Description: UNKNOWN Keywords:  Home-page: UNKNOWN Author: UNKNOWN Author-email: UNKNOWN Maintainer: UNKNOWN Maintainer-email: UNKNOWN License: UNKNOWN Classifier:  Download-URL: UNKNOWN Obsoletes-Dist: ['truffles (<=0.8,>=0.5)', 'truffles (<=0.9,>=0.6)'] Project-URL:  Provides-Dist: ['truffles (1.0)'] Requires-Dist: ['towel-stuff (0.1)'] Requires-Python: UNKNOWN Requires-External:  Extra ===== * It was installed as a dependency
Now, we take tackle a different problem, we are interested in finding out which distributions have been obsoleted. This can be easily done as follows:
from distutils2._backport import pkgutil # iterate over all distributions in the system for dist in pkgutil.get_distributions(): name = dist.name version = dist.metadata['Version'] # find out which distributions obsolete this name/version combination for obsoleted_by in pkgutil.obsoletes_distribution(name, version): print('%s(%s) is obsoleted by %s' % (name, version, obsoleted_by.name))
This is how the output might look like:
strawberry(0.6) is obsoleted by choxie grammar(1.0a4) is obsoleted by towel-stuff