内容


可爱的 Python

pydoc 和 distutils 模块

改善 Python 的社会基础

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: 可爱的 Python

敬请期待该系列的后续内容。

此内容是该系列的一部分:可爱的 Python

敬请期待该系列的后续内容。

一年前,如果您问一个诚实的 Python 推广者,Python 是否缺少某些如 Perl 等其它语言所拥有的重要的东西。答案很可能会是“是”。这并不是说 Python 缺少一定范围的模块和包的支持(包括 Python 自身和扩展模块)。这当然也不是 Python 胜人一筹的明确的表达式和简洁的面向对象。

建立在 Python 社区之上

Python 所欠缺的东西就是被 Perl 开发者描述为“社会因素”的东西。但即使这里,欠缺社会因素也并不意味着缺少一个积极的、智能的以及有支持力的 Python 社区 ― Python 有很多这样的社区。一年前的 Python 极度缺乏的是用来共享 Python 代码的充分规划的基础结构。代码共享是特定的、分散的和非常平凡的工作。

改进 Python 社会基础的第一步可能是 Tim Middleton 建立的 Vaults of Parnassus 网站(请参阅本文后面的 参考资料)。Python 开发者第一次拥有了一个专门的地方,那里有(几乎)所有已提供的第三方模块、包和工具。但这个地方仍有一些缺陷,使得这个网站可能比 Comprehensive Perl Archive Network 少了些优势(不过外表比后者更美观),Vaults 网站只是指向实际的资源位置,并不作为实际资源的镜像。网站由 Middleton 手工维护,有时候更新很慢;并且 Vex.Net (Vaults 坐落的站点)曾经有间歇断线的故障。但总的来说,Vaults of Parnassus 在建立强大的 Python 社区的架构先决条件方面提供了宝贵的资源。

有了这样一个公共站点,Python 社区所需的一切就是用一致的、可靠的方法安装所有这些可用的模块、包以及工具;再用同样简洁的方法指出它们所起的作用。随着标准 Python 发布的一些新标准模块也给出了解决方法。

pydoc

Ka-Ping Yee 曾创建了一个相当著名的模块,名叫 pydoc (比较而言: pydoc 可以做到 perldoc 所能做的任何事,并且做得更好、更漂亮:-)。对于 Python 2.1 来说, pydoc (以及它支持的 inspect )是标准库的一部分。而对于使用 Python 1.5.2、1.6 或者 2.0 版本的用户来说,下载并安装 pydoc 也很简单 ― 请立即下载(请参阅 参考资料)。

作为提供给阅读这篇 Python 文章的任何初学者的背景资料,Python 一直有些半正式的文档标准。这些标准并没有试图过度地限制开发者,而是给开发者提供“一种明显的写文档的方法。”幸运的是,通常情况下,Python 开发者所写的文档比使用其它语言的典型开发者所写的要好得多。

Python 文档之所以“优秀”的主要因素是使用所谓的“docstring”。虽然 docstring 实际上只是一个被称为 _doc_ 的变量,但还是有一个普遍使用的创建它们的快捷方式:只要在模块、函数 def 、类定义或方法 def 的头部放入一个简单的由(三重)引号括起来的字符串。此外,还有几个接近标准的模块级的“魔术”变量名被经常使用。尽管那些文档规则不太正式,但几乎所有第三方的模块和标准模块的文档都使用相同的模式。让我们来看一个使用大部分元素的简化示例:

清单 1: 附带典型文档的模块 mymod.py
#!/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

pydoc 模块利用了 Python 文档的约定,又使用了一些有关 Python 导入、继承和其它类似的实用知识。此外, pydoc 有绝对的天赋可以使自己在不同的操作模式下被使用(马上就能看到更多有关这个论点的资料)。让我们用一些时间,看看通过 OS 命令行调用的 manpage 风格的用法。

假设您已将上述模块 mymod 安装在您的系统上,但不知道它有什么用处(在示例中并不多)。您可以阅读源代码,不过更简单的方法可能是:

清单 2:获取‘manpage’风格的文档
% 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

根据特定的平台和安装过程,上述样本可能会显示在一个允许滚屏、搜索等功能并突出显示某些关键字的文本查看器中。对于像这样简单的示例,只是比纯粹的阅读源代码好一点。但请考虑一下像下面这样简单的示例:

清单 3:检查类的继承结构
% 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)

在这个快速报告中,我们可以知道 MyClass2__init__()foo() 方法(以及相应的参数),哪个方法是类自身实现的以及其它哪些方法是继承而来(以及被继承的类所处的位置)。

另一个美妙的类似于 manpage 的功能是用来在模块中搜索关键字的 -k 选项。例如:

清单 4:为任务定位适当的模块
% 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.
[...]

pydoc 除了它的命令行用法之外,还有其它四种“模式”可以显示被生成的同样的文档。

  • Shell 模式:在 Python 交互式 shell 中,您可以导入 pydochelp() 函数,这样就能够在不离开交互式会话的情况下获得任何对象的帮助。也可以只输入一个 help 进入交互式“help 解释器”。例如:

    清单 5:shell 模式下的交互式 help 解释器

    #------- 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 服务器模式:仅使用 -p 选项, pydoc 就会在 LOCALHOST 上作为一个简单的 Web 服务器自启动。您可以使用任何 Web 浏览器浏览所有已安装在现有操作系统上的模块。这个服务器的主页是一张模块列表,根据目录(并用浏览器支持的醒目色块)将它们分组。此外,您查看其文档的每个模块也广泛分布着它导入的函数、方法以及指向任何模块的链接。
  • HTML 生成器模式: -w 选项对于 pydoc 可以归档的任何文档都能生成 HTML 文档页面。这些页面与您在 Web 服务器模式下可能会浏览到的页面本质上是一回事,但页面是静态的,可以进行存档、传输等等。
  • TK 浏览器模式: -g 选项将创建一个和 xmantkman 风格很相似的“图形帮助浏览器。”

distutils

对于 Python 1.6 来说, distutils 包已经成为标准 Python 库的一部分。 distutils 包有两个目的。一方面, distutils 希望让最终用户觉得安装新模块、包和工具的过程一致而轻松。另一方面, distutils 还希望让新模块、包和工具的开发者觉得创建这些容易安装的分发包很轻松。让我们简要看一下这两个方面。

在最简单的情况下,开发者将已经选择为您特定的平台创建了安装程序。如果是这种情况,您其实根本不需要知道 distutils 的存在。目前, distutils 能够为支持 RPM 的 Linux 系统创建 RPM,为 Win32 系统创建 Windows EXE 安装程序。虽然这两个平台是主角,但还存在着其它平台,要么开发者可能已经有了适用于您的平台的解决方法(要么有创建一个安装程序的时间和兴趣)。

虽然没有最简单的例子,但幸运的是下一个出色的例子并没有复杂太多。假设您获取了一个支持 distutils 的源代码分发包,您可以依靠大量的东西(当然,在一切正常的情况下)。分发包的归档文件必须按照标准归档文件格式 ― 通常可以是 .zip 格式或 .tgz / .tar.gz 格式(偶尔会是 .tbz 格式或 tar.Z 格式, .sit 格式支持很快会添加到 MacOS 中去)。多数时候,Windows 用户使用 zip 格式文件,而 Linux/UNIX 用户使用 tarball 格式文件。不过要想在大多数平台上解包大部分的文件格式并不困难。一旦您将归档文件解包了,您就会获得一个文件集合,它被保存在与归档文件同名的目录里。例如:

清单 6:将一个 [distutils] 归档文件解包
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

大多数模块分发包的文件和目录会比这个例子中显示的要少。你真正需要的仅仅是文件 setup.py ,其中包含安装指令。但实际上,大家一致希望目录中有其它文件,这样 setup.py 就有可以安装的东西了。这里,您需要做的是:

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

至少那应该是您该做的事情。如果出现问题,请阅读(很可能也包含在 setup.py 中的) README.txtREADME 文件。然后,再查阅 Greg Ward 的 Installing Python Modules 文档。(请参阅 参考资料)。

接下来该做什么呢?您可以通过名字来猜测, setup.py 其实只是普通的 Python 脚本,所以当它运行时可以做任何事。但在大多数情况下 setup.py 会有一种相当固定的格式。可能看上去像这样:

清单 7:最小的 setup.py 安装脚本
#!/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'],
      )

这里真正的工作是由导入的 distutils 实现,特别是由 setup() 函数来实现。基本上, setup() 函数采用一组包含一列需要安装的东西(除 py_modules 外还可能有 packagesext_modules 或其它东西)的已命名的变量。

distutils 的魔力在于 创建模块分发包时利用安装时使用的完全相同的 setup.py 文件。一旦您 ― 模块开发者 ― 创建了一个 setup.py 脚本(也可能是‘setup.cfg’或其它扩展名)指定了需要安装的东西,创建分发包所要做的全部事情就是(下面的一步或几步):

清单 8:创建模块分发包
% python setup.py sdist
% python setup.py bdist_wininst
% python setup.py bdist_rpm

根据您指定的特定的分发包,您将创建一个标准的归档文件(tarball 或 zip 格式文件,取决于平台类型)或者一个完整的安装程序(像上面讨论过的那样)。

把两者结合在一起

虽然我们还没有完全达到目的,但是 Python 已经逐步成为最容易使用的编程语言的一种, 而且还是最容易使用的编程 社区的一种。虽然某些新的工具还有一些需要克服的缺陷,但在普遍意义上,让 Python 对用户透明这个要求已经实现了。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux
ArticleID=21587
ArticleTitle=可爱的 Python: pydoc 和 distutils 模块
publish-date=08012001