6. 示例 — Python 文档
6. 例子
本章提供了许多基本示例来帮助开始使用 distutils。 有关使用 distutils 的其他信息可以在 Distutils Cookbook 中找到。
6.1. 纯 Python 发行版(按模块)
如果您只是分发几个模块,特别是如果它们不在特定包中,则可以使用安装脚本中的 py_modules
选项单独指定它们。
在最简单的情况下,您需要担心两个文件:一个安装脚本和您分发的单个模块,在本例中为 foo.py
:
<root>/
setup.py
foo.py
(在本节的所有图表中,' 将引用分发根目录。)描述这种情况的最小安装脚本是:
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'],
)
您可以将模块源文件放到另一个目录中,但是如果您有足够的模块来执行此操作,那么按包指定模块可能比单独列出它们更容易。
6.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'],
)
6.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'])],
)
6.4. 检查包裹
check
命令允许您验证您的包元数据是否满足构建发行版的最低要求。
要运行它,只需使用您的 setup.py
脚本调用它。 如果缺少某些内容,check
将显示警告。
让我们以一个简单的脚本为例:
from distutils.core import setup
setup(name='foobar')
运行 check
命令将显示一些警告:
$ python setup.py check
running check
warning: check: missing required meta-data: version, url
warning: check: missing meta-data: either (author and author_email) or
(maintainer and maintainer_email) must be supplied
如果您在 long_description
字段中使用 reStructuredText 语法并且安装了 docutils,则可以使用 restructuredtext
命令检查语法是否正确] 选项。
例如,如果 setup.py
脚本更改如下:
from distutils.core import setup
desc = """\
My description
==============
This is the description of the ``foobar`` package.
"""
setup(name='foobar', version='1', author='tarek',
author_email='tarek@ziade.org',
url='http://example.com', long_description=desc)
如果长描述被破坏,check
将能够使用 docutils
解析器检测到它:
$ python setup.py check --restructuredtext
running check
warning: check: Title underline too short. (line 2)
warning: check: Could not finish the parsing.
6.5. 读取元数据
distutils.core.setup() 函数提供了一个命令行界面,允许您通过给定项目的 setup.py
脚本查询项目的元数据字段:
$ python setup.py --name
distribute
此调用通过运行 distutils.core.setup() 函数读取 name
元数据。 但是,当使用 Distutils 创建源或二进制分发时,元数据字段写入名为 PKG-INFO
的静态文件中。 当在 Python 中安装基于 Distutils 的项目时,PKG-INFO
文件与 NAME-VERSION-pyX.X.egg-info
下分发的模块和包一起复制,其中 NAME
是项目的名称, VERSION
元数据中定义的版本,pyX.X
Python 的主要和次要版本,如 2.7
或 3.2
。
您可以使用 distutils.dist.DistributionMetadata
类及其 read_pkg_file()
方法读回此静态文件:
>>> from distutils.dist import DistributionMetadata
>>> metadata = DistributionMetadata()
>>> metadata.read_pkg_file(open('distribute-0.6.8-py2.7.egg-info'))
>>> metadata.name
'distribute'
>>> metadata.version
'0.6.8'
>>> metadata.description
'Easily download, build, install, upgrade, and uninstall Python packages'
请注意,还可以使用元数据文件路径实例化该类以加载其值:
>>> pkg_info_path = 'distribute-0.6.8-py2.7.egg-info'
>>> DistributionMetadata(pkg_info_path).name
'distribute'