On this page
6. Distutils Examples
Note
该文档将一直保留,直到https://setuptools.readthedocs.io/en/latest/setuptools.html的setuptools
文档独立涵盖了此处当前包括的所有相关信息。
本章提供了一些基本示例,以帮助您开始使用 distutils。有关使用 distutils 的其他信息,请参见 Distutils Cookbook。
See also
食谱集,展示如何实现对 distutils 的更多控制。
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'],
)
请注意,发行版的名称是passname
选项独立指定的,没有规则说该名称必须与发行版中唯一模块的名称相同(尽管遵循的惯例可能不错)。但是,分发名称用于生成文件名,因此您应坚持字母,数字,下划线和连字符。
由于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'],
)
您可以将模块源文件放在另一个目录中,但是如果您有足够的模块来执行此操作,则pass包指定模块而不是单独列出它们可能会更容易。
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 不会*扫描您的源代码树,而是pass查找__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
extensions 属于根软件包,则此安装脚本可能是
from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
version='1.0',
ext_modules=[Extension('foo', ['foo.c'])],
)
如果 extensions 实际上属于某个包,请说foopkg
,然后
使用完全相同的源树布局,只需更改 extensions 即可将该扩展放入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
选项使用check
命令检查语法是否正确。
例如,如果像这样更改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()函数提供了一个命令行界面,使您可以pass给定项目的setup.py
脚本查询项目的元数据字段:
$ python setup.py --name
distribute
该调用pass运行distutils.core.setup()函数读取name
元数据。虽然,当使用 Distutils 创建源或二进制发行版时,元数据字段被写入称为PKG-INFO
的静态文件中。当在 Python 中安装基于 Distutils 的项目时,PKG-INFO
文件将与分发的模块和软件包一起在NAME-VERSION-pyX.X.egg-info
下复制,其中NAME
是项目的名称,VERSION
是其在元数据中定义的版本,而pyX.X
是主要和诸如2.7
或3.2
的 Python 的次要版本。
您可以使用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'