6. Distutils示例¶
注解
本文件仅保留至 setuptools
https://setuptools.readthedocs.io/en/latest/setuptools.html上的文档独立地涵盖了此处当前包含的所有相关信息。
本章提供了一些基本示例,以帮助开始使用distutils。有关使用distutils的其他信息,请参阅distutils秘诀。
参见
- Distutils Cookbook
显示如何对distuils实现更多控制的秘诀集合。
6.1. 纯Python分发(按模块)¶
如果您只是分发几个模块,特别是如果它们不存在于特定的包中,那么可以使用 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'],
)
您可以将模块源文件放在另一个目录中,但如果您有足够的模块来执行此操作,那么按包指定模块可能会更容易,而不是单独列出模块。
6.2. 纯Python分发(按包)¶
如果要分发多个模块,尤其是在多个包中,那么指定整个包而不是单个模块可能更容易。即使您的模块不在包中,也可以这样做;您只需告诉distuils从根包中处理模块,它的工作方式与任何其他包相同(除了您不需要 __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
这实际上是distuils所期望的默认布局,并且是安装脚本中描述的工作最少的布局:
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 not 扫描源代码树,通过查找 __init__.py
因此,如果默认布局增加子包:
<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) should be supplied
如果在 long_description
字段和 docutils 已安装。您可以检查语法是否符合 check
命令,使用 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
此调用显示 name
通过运行 distutils.core.setup()
功能。但是,当使用distuils创建源或二进制分发时,元数据字段将写入名为 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'