# 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` 是个列表，你当然可以指定多个模块，比如，如果你要分发模块 `foo` 和 `bar`，你的配置可能是这样：

    <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=[''],
          )

更一般地，你要分发多个在同一个包（或者子包）中的模块。举个例子，假设 `foo` 和 `bar` 模块属于 `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'])],
          )