7. 例子

本章节提供几个基础示例,来帮助用户入门 distutils。关于使用 distutils 的额外信息可以参考 Distutils Cookbook。

参见

Distutils Cookbook

一套展示如何更好地控制和使用 distutils 的方法。

7.1. 纯 Python 分发(通过 module)

如果你要分发一组模块,特别是它们不在特定的包中,你可以在配置脚本中使用 py_modules 选项单独指定它们。

最简单的情况下,你只用关心两个文件:一个配置脚本,和单个你要分发的模块,这个示例中的 foo.py: :

<root>/
        setup.py
        foo.py

(在本章节的所有图中,<root> 表示分发根目录。)这种情况下的一个最小配置脚本是:

from distutils.core import setup
setup(name='foo',
      version='1.0',
      py_modules=['foo'],
      )

注意分发的包名用 name 选项单独指定,没有规定它必须和包中单独的模块同名(虽然这也是个可以遵循的好习惯)。然而,分发名用来生成文件名,所以你应该坚持用字母、数字、下划线和连词号。

因为 py_modules 是个列表,你当然可以指定多个模块,比如,如果你要分发模块 foobar,你的配置可能是这样:

<root>/
        setup.py
        foo.py
        bar.py

并且配置脚本是:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      py_modules=['foo', 'bar'],
      )

你可以把模块源文件放进另一个目录,但是如果你有足够的模块,也许用包指定模块更简单,而不是单独列出它们。

7.2. 纯 Python 分发(通过 包)

如果你有超过一组模块要分发,特别是它们在不同的包中,也许指定整个包更简单,而不是指定单独的模块。这样即使你的模块不在一个包中也有效;你可以直接令 Distutils 来从根包来处理模块,并且这样对任何其他包也有效(除非你不需要 __init__.py 文件)。

上一个示例的配置脚本也可以写成:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      packages=[''],
      )

(空字符串表示根包。)

如果两个文件移动到子目录,但是依然在根包中,如:

<root>/
        setup.py
        src/      foo.py
                  bar.py

那么你依然需要指定根包,但是你还需要告诉 Distutils 根包中的源文件在哪:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      package_dir={'': 'src'},
      packages=[''],
      )

更一般地,你要分发多个在同一个包(或者子包)中的模块。举个例子,假设 foobar 模块属于 foobar 包,排布源文件树的一种方式是:

<root>/
        setup.py
        foobar/
                 __init__.py
                 foo.py
                 bar.py

这其实是 Distutils 默认的排布,也是你的配置脚本中需要的工作量最小的。

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      packages=['foobar'],
      )

如果你要把模块放到没有按照它们的包名命名的目录里,那你需要再次使用 package_dir 选项。比如,如果 src 目录包含包 foobar 中的模块:

<root>/
        setup.py
        src/
                 __init__.py
                 foo.py
                 bar.py

一个合适的配置脚本可以是:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      package_dir={'foobar': 'src'},
      packages=['foobar'],
      )

或者,你可以把主包中的模块直接放到分发根目录:

<root>/
        setup.py
        __init__.py
        foo.py
        bar.py

这样你的配置文件是:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      package_dir={'foobar': ''},
      packages=['foobar'],
      )

(空字符串同样表示当前目录。)

如果你有子包,则它们必须显式列在 packages 中,但是 package_dir 中的任何条目会自动扩展到子包。(也就是说,Distutils 不会 扫描你的源码树,而是尝试通过查找 __init__.py 文件,来弄清哪些目录与 Python 包关联。)这样,如果默认排布产生一个子包:

<root>/
        setup.py
        foobar/
                 __init__.py
                 foo.py
                 bar.py
                 subfoo/
                           __init__.py
                           blah.py

则相应的配置脚本是:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      packages=['foobar', 'foobar.subfoo'],
      )

7.3. 单个扩展模块

扩展模块用 ext_modules 选项指定。package_dir 对在哪寻找扩展源文件无效;它只对纯 Python 模块的源文件有效。最简单的,一个用单个C源文件写的单扩展模块是:

<root>/
        setup.py
        foo.c

如果 foo 扩展属于根包,则配置脚本可以是:

from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
      version='1.0',
      ext_modules=[Extension('foo', ['foo.c'])],
      )

如果扩展在包中,比如 foopkg,那么

使用完全相同的源文件树排布,通过改变扩展的名字,这个扩展很容易放入 foopkg 包中:

from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
      version='1.0',
      ext_modules=[Extension('foopkg.foo', ['foo.c'])],
      )