用于隔离Python发行版(包和脚本)的配方。
项目描述
此构建配方仅用于隔离分发包及其依赖项。此配方最初是为在Debian操作系统中对Zope2进行打包而开发的。此配方还可以用于填充Python环境(或虚拟环境)。在需要buildout构建应用程序,但开发人员/系统管理员希望在典型的Python环境中使用应用程序的情况下,这可能很有用。
分发隔离
可以使用 buildout.recipe.isolation 配方在单个目录中隔离分发和其依赖项。该配方包含一些选项
- dists
要隔离的分布列表,作为一个或多个setuptools需求字符串给出。每个需求字符串应单独一行给出。默认使用部分名称作为分发。
- exclude-dists(可选)
要排除隔离的分布列表。
- dists-location(可选)
将隔离的分布放置的目录位置。此选项默认为在配方使用的部分名称下的buildout部分目录中的位置。
- scripts-location(可选)
一个目录位置,用于隔离分发脚本。此选项默认为构建部分目录下部分(或章节)名称后跟“-scripts”的位置(例如,对于名为 isolated 的部分,默认脚本目录名称将是 isolated-scripts)。
- pth-location(可选)
创建此隔离的 .pth 文件的目录位置。此选项默认为构建部分目录下部分(或章节)名称后跟“-pth”的位置(例如,对于名为 isolated 的部分,默认 pth 目录名称将是 isolated-pth)。
pth 文件的最终名称将是部分名称,后跟 .pth 扩展名。要引用生成的 .pth 文件,请使用 pth-file-location 选项。
- pth-file-location(仅参考)
.pth 文件所在的路径。生成的 .pth 文件在脚本生成过程中使用,以提供位于文件系统另一处的隔离分布的列表。
- extra-pth(可选)
要作为脚本初始化部分包括的 .pth 文件列表。
此选项解决了由依赖隔离引起的依赖性问题。例如,如果您正在使用 exclude-dists,并且要排除的分布需要运行脚本,您可能希望包括包含这些依赖项位置的 .pth 文件。
- exclude-own-pth(可选)
一个布尔选项,当设置时,将排除上下文部分生成的 .pth 文件在脚本中的包含。此选项与 pth-file-location 和 extra-pth 密切相关。此选项默认为 false。
此选项被包含的原因是 .pth 文件中的位置已经通过 site-packages 中 .pth 文件的位置包含在 Python 路径中。
- executable(可选)
Python 可执行文件的位置。默认情况下这是 sys.executable。
指定的可执行文件在食谱中未执行。位置在脚本生成期间用作 shebang 行。
- stage-locally(可选)
一个布尔选项,用于指定我们是否应将资源存档或将其放置在最终目标位置。如果此选项为 true,则使用 dist-location、script-location 和 pth-location 指定的值生成资源,但资源放置在默认部分位置。此选项对存档安装很有用。
食谱交付成果
包含指定分布(s)包及其依赖包(s)的目录。
包含 .pth 文件的目录,其中列出隔离上下文中每个包的绝对路径。
包含从分布(s)包及其依赖包生成的脚本。
工作原理
我们有一个示例 buildout。让我们更新其配置文件以安装演示包。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = demo ... ... [demo] ... recipe = buildout.recipe.isolation ... dists = demo<0.3 ... find-links = %(server)s ... index = %(server)s/index ... """ % dict(server=link_server))
在此示例中,我们将范围限制在 0.3 之前的修订版。我们还指定了使用 find-links 选项查找分布的位置。
为了控制分布测试数据,我们决定使用 buildout 的测试索引,如下所示
>>> print get(link_server), <html><body> <a href="bigdemo-0.1-py2.3.egg">bigdemo-0.1-pyN.N.egg</a><br> <a href="demo-0.1-py2.3.egg">demo-0.1-py2.3.egg</a><br> <a href="demo-0.2-py2.3.egg">demo-0.2-py2.3.egg</a><br> <a href="demo-0.3-py2.3.egg">demo-0.3-py2.3.egg</a><br> <a href="demo-0.4c1-py2.3.egg">demo-0.4c1-py2.3.egg</a><br> <a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br> <a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br> <a href="demoneeded-1.2c1.zip">demoneeded-1.2c1.zip</a><br> <a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br> <a href="index/">index/</a><br> <a href="other-1.0-py2.3.egg">other-1.0-py2.3.egg</a><br> </body></html>
我们将通过测试结构使用此索引,并进一步解释在各个分布之前的这些关系。
让我们运行 buildout
>>> import os >>> print system(buildout), #doctest: +ELLIPSIS Installing demo. Getting distribution for 'demo<0.3'. Got demo 0.2. Getting distribution for 'demoneeded'. install_dir ... Got demoneeded 1.2c1. demo: Copying demo to the destination directory. demo: Copying demoneeded to the destination directory. demo: Generated script '/sample-buildout/parts/demo-scripts/demo'.
现在,如果我们查看隔离的 buildout 部分目录
>>> ls(sample_buildout, 'parts/demo') - demo-0.2-py2.3.egg d demoneeded-1.2c1-py2.3.egg
这些分布已进入 .pth 文件。此文件对 buildout 没有直接用途,但在 Python 环境中有其位置。.pth 文件的内容将是已安装到隔离中的每个分布的绝对路径。让我们看一下
>>> cat(sample_buildout, 'parts/demo-pth', 'demo.pth') /sample-buildout/parts/demo/demo-0.2-py2.6.egg /sample-buildout/parts/demo/demoneeded-1.2c1-py2.6.egg
默认情况下,.pth 文件的名称将与构建部分名称相同,在本例中为 demo。您可以使用 pth-file-location 选项更改 .pth 文件的位置。
依赖排除
现在让我们尝试一个稍大一些的示例构建,我们可以用它来展示从特定隔离中排除依赖项。
让我们根据上一个构建配置创建一个新的构建配置。此配置已设置为隔离 bigdemo 分发及其依赖项,但排除 demoneeded 依赖项。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = ... demoneeded ... demo ... find-links = %(server)s ... index = %(server)s/index ... ... [demoneeded] ... recipe = buildout.recipe.isolation ... dists = demoneeded ... ... [demo] ... recipe = buildout.recipe.isolation ... dists = bigdemo ... exclude-dists = ${demoneeded:dists} ... """ % dict(server=link_server))>>> print system(buildout), #doctest: +ELLIPSIS Uninstalling demo. Installing demoneeded. demoneeded: Copying demoneeded to the destination directory. Installing demo. Getting distribution for 'bigdemo'. Got bigdemo 0.1. Getting distribution for 'demo'. Got demo 0.4c1. demo: Copying demo to the destination directory. demo: Copying bigdemo to the destination directory. demo: Generated script '/sample-buildout/parts/demo-scripts/demo'.
检查隔离结果
>>> ls(sample_buildout, 'parts/demo') - bigdemo-0.1-py2.6.egg - demo-0.4c1-py2.6.egg >>> ls(sample_buildout, 'parts/demoneeded') d demoneeded-1.2c1-py2.6.egg
脚本生成
某些分发在其软件包中提供命令行脚本。Buildout 通常为我们生成这些脚本,因为它需要向脚本提供构建的软件包。它通过将分发位置注入 Python 系统路径来完成此操作。在某些情况下,我们不希望将任何内容注入 Python 系统路径,因为我们可能已经将生成的 .pth 文件放置在虚拟环境的 site-packages 目录中。而在其他情况下,我们可能希望将 .pth 文件作为导入解析的手段提供。让我们更仔细地看看这两种情况。
对于一般情况,我们可能希望将我们的 .pth 文件提供给脚本。此外,我们可能还希望提供任何依赖隔离可能生成的 .pth 文件。以下是一个示例。
>>> import sys >>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = ... demoneeded ... demo ... find-links = %(server)s ... index = %(server)s/index ... ... [demoneeded] ... recipe = buildout.recipe.isolation ... dists = demoneeded ... ... [demo] ... recipe = buildout.recipe.isolation ... dists = bigdemo ... exclude-dists = ${demoneeded:dists} ... extra-pth = ${demoneeded:pth-file-location} ... executable = %(python)s ... """ % dict(server=link_server, python=sys.executable)) >>> print system(buildout), #doctest: +ELLIPSIS Uninstalling demo. Uninstalling demoneeded. Installing demoneeded. demoneeded: Copying demoneeded to the destination directory. Installing demo. demo: Copying demo to the destination directory. demo: Copying bigdemo to the destination directory. demo: Generated script '/sample-buildout/parts/demo-scripts/demo'.
生成的脚本应包含两个 .pth 文件。demo.pth 文件已定义并从上下文中的配方生成。demoneeded.pth 文件是由 demoneeded 部分生成的,并使用 extra-pth 配方选项引入。
>>> if sys.platform == 'win32': ... script_name = 'demo-script.py' ... else: ... script_name = 'demo' >>> script_dir = 'parts/demo-scripts' >>> f = open(os.path.join(sample_buildout, script_dir, script_name)) >>> shebang = f.readline().strip() >>> if shebang[:3] == '#!"' and shebang[-1] == '"': ... shebang = '#!'+shebang[3:-1] >>> shebang == '#!' + os.path.realpath(sys.executable) True >>> print f.read(), # doctest: +NORMALIZE_WHITESPACE <BLANKLINE> import sys def pth_injector(pth_file): path_file = open(pth_file, 'r') sys.path[0:0] = [line for line in path_file.read().split('\n') if line is not None] <BLANKLINE> pth_files = ['/sample-buildout/parts/demo-pth/demo.pth', '/sample-buildout/parts/demoneeded-pth/demoneeded.pth'] for pth in pth_files: pth_injector(pth) <BLANKLINE> import eggrecipedemo <BLANKLINE> if __name__ == '__main__': eggrecipedemo.main() >>> f.close()
第二种情况是将 .pth 文件存放到虚拟环境中。让我们为了演示的目的,在构建结构内部设置一个 伪造 的虚拟环境结构。
>>> virtenv = os.path.join(sample_buildout, 'virtenv') >>> mkdir(virtenv) >>> mkdir(virtenv, 'bin') >>> mkdir(virtenv, 'lib') >>> mkdir(virtenv, 'lib', 'python2.6') >>> mkdir(virtenv, 'lib', 'python2.6', 'site-packages') >>> site_pkgs = os.path.join(virtenv, 'lib', 'python2.6', 'site-packages')
对于这个演示,我们实际上只需要 site-packages 目录。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = ... demoneeded ... demo ... find-links = %(server)s ... index = %(server)s/index ... ... [demoneeded] ... recipe = buildout.recipe.isolation ... dists = demoneeded ... pth-file-location = %(site_pkgs)s ... ... [demo] ... recipe = buildout.recipe.isolation ... dists = bigdemo ... exclude-dists = ${demoneeded:dists} ... pth-file-location = %(site_pkgs)s ... exclude-own-pth = trUE ... python = %(python)s ... """ % dict(server=link_server, python=sys.executable, ... site_pkgs=site_pkgs)) >>> print system(buildout), #doctest: +ELLIPSIS Uninstalling demo. Uninstalling demoneeded. Installing demoneeded. demoneeded: Copying demoneeded to the destination directory. Installing demo. demo: Copying demo to the destination directory. demo: Copying bigdemo to the destination directory. demo: Generated script '/sample-buildout/parts/demo-scripts/demo'.
现在,如果我们打印出 demo 脚本,我们会发现没有提到 .pth 文件。
>>> f = open(os.path.join(sample_buildout, script_dir, script_name)) >>> shebang = f.readline().strip() >>> if shebang[:3] == '#!"' and shebang[-1] == '"': ... shebang = '#!'+shebang[3:-1] >>> shebang == '#!' + os.path.realpath(sys.executable) True >>> print f.read(), # doctest: +NORMALIZE_WHITESPACE <BLANKLINE> import eggrecipedemo <BLANKLINE> if __name__ == '__main__': eggrecipedemo.main() >>> f.close()
为什么这会起作用?如果我们使用虚拟环境的 Python 可执行文件,它会加载 site-packages 目录以及其中的任何 .pth 文件。这将反过来加载我们使用构建生成的模块。
隔离的预演
在某些情况下,在将资源传输到最终目的地之前在本地构建软件包很有用。为此,我们可以使用 stage-locally 选项对隔离过程进行预演。
此选项将允许您设置 dists-location、scripts-location 和 pth-file-location 作为最终目的地,但将结果放置在其默认构建位置。如果您还记得,默认构建位置在构建的 parts 目录中。
让我们通过创建一个类似的构建配置来了解这是如何工作的,但现在我们将 stage-locally 选项设置为 true。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = ... demo ... find-links = %(server)s ... index = %(server)s/index ... ... [demo] ... recipe = buildout.recipe.isolation ... dists = bigdemo ... dists-location = %(site_pkgs)s ... scripts-location = %(bin_dir)s ... pth-location = %(site_pkgs)s ... executable = %(python)s ... stage-locally = true ... """ % dict(server=link_server, ... bin_dir=os.path.join(virtenv, 'bin'), ... python=os.path.join(virtenv, 'bin', 'python'), ... site_pkgs=site_pkgs)) >>> print system(buildout), #doctest: +ELLIPSIS Uninstalling demo. Uninstalling demoneeded. Installing demo. demo: Copying demo to the staging directory. demo: Copying demoneeded to the staging directory. demo: Copying bigdemo to the staging directory. demo: Can't find the executable on the filesystem. Perhaps this setup is not destine to be used on this machine. So we are using the given executable value /sample-buildout/virtenv/bin/python as is. demo: Generated script '/sample-buildout/parts/demo-scripts/demo'.
为了验证事物已被部署,让我们仔细查看演示脚本以确认一切是否按计划进行。首先,我们期望脚本位于parts目录中
>>> parts_dir = os.path.join(sample_buildout, 'parts') >>> demo_script = os.path.join(parts_dir, 'demo-scripts', 'demo') >>> os.path.exists(demo_script) True >>> cat(demo_script) #!/sample-buildout/virtenv/bin/python <BLANKLINE> import sys def pth_injector(pth_file): path_file = open(pth_file, 'r') sys.path[0:0] = [line for line in path_file.read().split('\n') if line is not None] <BLANKLINE> pth_files = ['/sample-buildout/virtenv/lib/python2.6/site-packages/demo.pth'] for pth in pth_files: pth_injector(pth) <BLANKLINE> import eggrecipedemo <BLANKLINE> if __name__ == '__main__': eggrecipedemo.main()
此外,我们还想检查pth位置是否正确,并且pth本身是否与parts一起位于部署区域
>>> demo_pth = os.path.join(parts_dir, 'demo-pth', 'demo.pth') >>> cat(demo_pth) /sample-buildout/virtenv/lib/python2.6/site-packages/demo-0.4c1-py2.1.egg /sample-buildout/virtenv/lib/python2.6/site-packages/demoneeded-1.2c1-py2.1.egg /sample-buildout/virtenv/lib/python2.6/site-packages/bigdemo-0.1-py2.1.egg
问题和帮助
如果您有问题或需要帮助,请向WebLion的项目网站提交错误报告,或通过IRC或电子邮件联系我们。
项目详情
下载文件
下载适用于您的平台文件。如果您不确定选择哪个,请了解有关安装包的更多信息。
源分发
buildout.recipe.isolation-0.2.0.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 6d9a8c1c4bc6e9ea98b2066ec8e19106486b2074c65b649b0b62c612a692e2c3 |
|
MD5 | 501881dfc4b1306f5a0b7eaf934726f2 |
|
BLAKE2b-256 | 371430539ce8cc22c4b89f0832c015b4daafad0b6e878dd06ce7fcd1a13e7618 |