The pydoc module and distutils module in Python are introduced

  • 2020-05-09 18:45:05
  • OfStack

pydoc

Ka-Ping Yee has created a rather famous module called pydoc (by comparison: pydoc can do anything perldoc can do, and do it better and prettier :-). For Python 2.1, pydoc (and the inspect it supports) is part 1 of the standard library. For users of Python versions 1.5.2, 1.6, or 2.0, it is also easy to download and install pydoc immediately (see resources).

As background for any beginner reading this Python article, Python 1 has some semi-formal documentation standards. Rather than trying to restrict developers too much, these standards provide "an obvious way to document." Fortunately, in general, the documentation written by Python developers is much better than that written by typical developers in other languages.

The main factor that makes Python documents "good" is the use of what is known as "docstring." Although docstring is really just a variable called _doc_, there is a commonly used shortcut for creating them: simply put a simple string enclosed in (3) quotes at the head of a module, function def, class definition, or method def. In addition, several near-standard module-level "magic" variable names are frequently used. Although those document rules are less formal, almost all third party and standard module documents use the same schema. Let's look at a simplified example that USES most elements:
Listing 1: module mymod.py with typical documentation


#!/usr/bin/python
"""Show off features of [pydoc] module
This is a silly module to
demonstrate docstrings
"""
__author__ = 'David Mertz'
__version__= '1.0'
__nonsense__ = 'jabberwocky'
class MyClass:
  """Demonstrate class docstrings"""
  def __init__ (self, spam=1, eggs=2):
    """Set default attribute values only
    Keyword arguments:
    spam  �  a processed meat product
    eggs  �  a fine breakfast for lumberjacks
    """
    self.spam = spam
    self.eggs = eggs

The pydoc module takes advantage of the conventions of the Python documentation and USES some practical knowledge about Python imports, inheritance, and the like. In addition, pydoc has an absolute gift for being used in different modes of operation (see more on this in a moment). Let's take a moment to look at manpage style usage invoked from the OS command line.

Let's say you have the above module mymod installed on your system, but you don't know what it does (not much in this example). You can read the source code, but a simpler approach might be:
Listing 2: get the 'manpage' style document


% pydoc.py mymod
Python Library Documentation: module mymod
NAME
  mymod - Show off features of [pydoc] module
FILE
  /articles/scratch/cp18/mymod.py
DESCRIPTION
  This is a silly module to
  demonstrate docstrings
CLASSES
  MyClass
  class MyClass
   | Demonstrate class docstrings
   |
   | __init__(self, spam=1, eggs=2)
   |   Set default attribute values only
   |
   |   Keyword arguments:
   |   spam  �  a processed meat product
   |   eggs  �  a fine breakfast for lumberjacks
DATA
  __author__ = 'David Mertz'
  __file__ = './mymod.pyc'
  __name__ = 'mymod'
  __nonsense__ = 'jabberwocky'
  __version__ = '1.0'
VERSION
  1.0
AUTHOR
  David Mertz

Depending on the particular platform and installation process, the sample might be displayed in a text viewer that allows scrolling, searching, and so on, and highlights certain keywords. For a simple example like this, it's just 1 point better than just reading the source code. But consider a simple example like this:
Listing 3: checking the inheritance structure of the class


% cat mymod2.py
from mymod import MyClass
class MyClass2(MyClass):
  """Child class"""
  def foo(self):
    pass
% pydoc.py mymod2.MyClass2
Python Library Documentation: class MyClass2 in mymod2
class MyClass2(mymod.MyClass)
 | Child class
 |
 | __init__(self, spam=1, eggs=2) from mymod.MyClass
 |
 | foo(self)

In this quick report, we can know which methods MyClass2 have s 53en__ () and s 54en () methods (and the corresponding parameters), which methods are implemented by the class itself, and which other methods are inherited (and where the inherited class is located).

Another nice manpage-like feature is the -k option for searching for keywords in modules. Such as:
Listing 4: locate the appropriate module for the task


% pydoc.py -k uuencode
uu - Implementation of the UUencode and UUdecode functions.
% pydoc.py uu
Python Library Documentation: module uu
NAME
  uu - Implementation of the UUencode and UUdecode functions.
[...]

In addition to its command line usage, pydoc has four other "patterns" that display the same documents that are generated.

      Shell mode: in Python interactive shell, you can import pydoc's help() function so that you can get help from any object without leaving the interactive session. You can also enter only one help into the interactive "help interpreter." Such as:

Listing 5:       interactive help interpreter in shell mode


  #------- Interactive shell with help enhancements ------#
  >>> from pydoc import help
  >>> import uu
  >>> help(uu.test)
  Help on function test in module uu:
  test()
   uuencode/uudecode main program
  >>> help
  Welcome to Python 2.0! This is the online help utility.
  [...introductory message about help shell...]
  help>

      Web server mode: using only the -p option, pydoc starts itself as a simple Web server on LOCALHOST. You can use any Web browser to browse through all the modules that have been installed on your existing operating system. The home page of the server is a list of modules, grouped by directory (and with browser-supported bold color blocks). In addition, each module whose documentation you view is widely distributed with its imported functions, methods, and links to any module.       HTML generator mode: -w option generates HTML document pages for any document that pydoc can archive. These pages are essentially the same as the pages you might see in Web server mode, but the pages are static and can be archived, transferred, and so on. The       TK browser mode: -g option will create a "graphical help browser" similar to the xman or tkman style.

distutils

For Python 1.6, the distutils package has become part 1 of the standard Python library. The distutils package serves two purposes. On the one hand, distutils wants to make the process of installing new modules, packages, and tools easy for end users. On the other hand, distutils also wants to make it easy for developers of new modules, packages, and tools to create these easy-to-install distributions. Let's look briefly at these two aspects.

In the simplest case, the developer will have chosen to create the installer for your particular platform. If this is the case, you don't really need to know that distutils exists at all. Currently, distutils is able to create RPM for Linux systems that support RPM, and Windows EXE installers for Win32 systems. While these two platforms are the main players, there are other platforms out there, and either the developer may already have a solution for your platform (or the time and interest to create an installer).

There is no simple example, but fortunately the next great example is not too complicated. Assuming you get a source code distribution that supports distutils, you can rely on a lot of things (if the 1-slice is normal, of course). The distribution package archive must be in the standard archive format.zip or.tgz /.tar.gz (occasionally.tbz or tar.Z;.sit support will soon be added to MacOS). Most of the time, Windows users use zip files, while Linux/UNIX users use tarball files. However, it is not difficult to unpack most file formats on most platforms. Once you unpack the archive, you get a collection of files stored in a directory with the same name as the archive. Such as:
Listing 6: unpacking one [distutils] archive


E:\Archive\devel>unzip -q Distutils-1_0_2.zip
E:\Archive\devel>cd Distutils-1.0.2
E:\Archive\devel\Distutils-1.0.2>ls
The volume label in drive E is ARCHIVE.
The Volume Serial Number is E825:C814.
Directory of E:\Archive\devel\Distutils-1.0.2
 6-14-01  0:38a   <DIR>      0 .
 6-14-01  0:38a   <DIR>      0 ..
 5-03-01  6:30p   15355      0 CHANGES.txt
 5-03-01  6:32p   <DIR>      0 distutils
 5-03-01  6:32p   <DIR>      0 doc
 5-03-01  6:32p   <DIR>      0 examples
10-02-00 11:47p    373      0 MANIFEST.in
 5-03-01  6:32p   <DIR>      0 misc
 5-03-01  6:32p    496      0 PKG-INFO
 4-20-01  2:30p   14407      0 README.txt
 6-29-00 11:45p   1615      0 setup.cfg
 5-03-01  6:17p   1120      0 setup.py
 4-20-01  2:29p   9116      0 TODO
 4-11-00  9:40p    836      0 USAGE.txt

Most module distributions will have fewer files and directories than shown in this example. All you really need is the file setup.py, which contains the installation instructions. In fact, you'd like to have other files in your directory so that setup.py has something to install. Here's what you need to do:


  E:\archive\devel\Distutils-1.0.2> python setup.py install

At least that's what you should be doing. If there is a problem, please read the README.txt or README files (most likely included in setup.py). Then, refer to the Installing Python Modules documentation for Greg Ward. (see resources).

What to do next? You can guess by name that setup.py is really just a normal Python script, so it can do anything when it's run. But in most cases setup.py has a fairly fixed format. It might look something like this:
Listing 7: the smallest setup.py installation script


#!/usr/bin/env python
"""Setup script for the sample #1 module distribution:
  single top-level pure Python module, named explicitly
  in 'py_modules'."""
from distutils.core import setup
setup (# Distribution meta-data
    name = "sample",
    version = "1.0",
    description = "Distutils sample distribution #1",
# Description of modules and packages in the distribution
    py_modules = ['sample'],
   )

The real work here is done by the imported distutils implementation, specifically by the setup() function. Basically, the setup() function takes a set of named variables that contain what you need to install in column 1 (in addition to py_modules, you might also have packages or ext_modules or something else).

The magic of distutils is to create the module distribution using the exact same setup.py file that you used when you installed it. Once you have created an setup.py script (or 'setup.cfg' or some other extension) that specifies what needs to be installed, all you need to do to create a distribution is (step 1 or 2 below) :
Listing 8: creating the module distribution


% python setup.py sdist
% python setup.py bdist_wininst
% python setup.py bdist_rpm

Depending on the particular distribution you specify, you will create either a standard archive (tarball or zip, depending on the platform type) or a full installer (as discussed above).

Combine the two in 1

While we're not quite there yet, Python is on its way to becoming one of the easiest programming languages to use and one of the easiest programming communities to use. While some of the new tools have some drawbacks to overcome, the requirement to make Python transparent to users in general has been met.


Related articles: