28.4. zipapp
- 管理可执行文件python zip档案¶
版本3.5中的新功能。
源代码: Lib / zipapp.py
此模块提供的工具可用于管理包含Python代码的zip文件的创建,这种zip文件可直接被Python解释器执行。该模块提供命令行界面和Python API。
28.4.1. Basic Example¶
以下示例说明如何从包含Python代码的目录使用命令行界面创建可执行文件。When run, the archive will execute the main
function from the module myapp
in the archive.
$ python -m zipapp myapp -m "myapp:main"
$ python myapp.pyz
<output from myapp>
28.4.2. Command-Line Interface¶
当从命令行调用为程序时,使用以下形式:
$ python -m zipapp source [options]
如果source是目录,则将从源的内容创建归档。如果source是一个文件,它应该是一个存档,并且它将被复制到目标存档(或者如果指定了-info选项,则将显示其shebang行的内容)。
以下选项被理解:
-
-o
<output>
,
--output
=<output>
¶ 将输出写入名为输出的文件。如果未指定此选项,则输出文件名将与输入源相同,并添加了扩展名
.pyz
。如果给定了显式文件名,则按原样使用(因此,如果需要,应包括.pyz
扩展名)。如果源是存档(在这种情况下,输出不能与源相同),则必须指定输出文件名。
-
-p
<interpreter>
,
--python
=<interpreter>
¶ 添加
#!
行到指定解释器的档案作为要运行的命令。此外,在POSIX上,使归档可执行。默认值为不写#!
行,并且不使文件可执行。
-
-m
<mainfn>
,
--main
=<mainfn>
¶ 将
__main__.py
文件写入执行mainfn的存档。mainfn参数的格式应为“pkg.mod:fn”,其中“pkg.mod”是存档中的包/模块,“fn”是给定模块中的可调用。__main__.py
文件将执行该可调用。复制存档时无法指定
--main
。
-
--info
¶
显示嵌入在归档中的解释器,用于诊断目的。在这种情况下,将忽略任何其他选项,SOURCE必须是存档,而不是目录。
-
-h
,
--help
¶
打印简短的使用消息并退出。
28.4.3. Python API¶
模块定义了两个方便的功能:
-
zipapp.
create_archive
(source, target=None, interpreter=None, main=None)¶ 从源创建应用程序归档。源可以是以下任何一种:
- 目录的名称或指向目录的
pathlib.Path
对象,在这种情况下,将从该目录的内容创建新的应用程序归档。 - 现有应用程序归档文件的名称或引用此类文件的
pathlib.Path
对象,在这种情况下,将文件复制到目标(修改它以反映为>解释器参数)。如果需要,文件名应包含.pyz
扩展名。 - 以字节模式读取的文件对象。文件的内容应该是应用程序归档,并且文件对象假定位于归档的开始。
目标参数确定将写入结果归档的位置:
- 如果它是文件的名称或
pathlb.Path
对象,则归档将写入该文件。 - 如果它是一个打开的文件对象,则归档将被写入该文件对象,该对象必须打开以便以字节模式写入。
- 如果省略目标(或无),则源必须是目录,目标将是与源相同名称的文件,并添加了
.pyz
扩展名。
解释器参数指定将要执行归档的Python解释器的名称。它在归档开始时写为“shebang”行。在POSIX上,这将被操作系统解释,在Windows上它将由Python启动程序处理。省略解释器会导致没有写入shebang行。如果指定了解释器,并且目标是文件名,则将设置目标文件的可执行位。
main参数指定将用作归档的主程序的可调用的名称。它只能在源是目录且源尚未包含
__main__.py
文件时才能指定。main参数应采用“pkg.module:callable”的形式,并且通过导入“pkg.module”并执行没有参数的给定callable来运行归档。如果源是目录并且不包含__main__.py
文件,则省略main是错误,否则生成的归档将不可执行。如果为source或target指定了文件对象,则调用create_archive后,调用者应负责关闭它。
复制现有存档时,提供的文件对象只需要
read
和readline
或write
方法。从目录创建归档时,如果目标是文件对象,则它将传递到zipfile.ZipFile
类,并且必须提供该类所需的方法。- 目录的名称或指向目录的
28.4.4. Examples¶
将目录封装到归档中,并运行它。
$ python -m zipapp myapp
$ python myapp.pyz
<output from myapp>
同样可以使用create_archive()
functon:
>>> import zipapp
>>> zipapp.create_archive('myapp.pyz', 'myapp')
要使应用程序在POSIX上可直接执行,请指定要使用的解释器。
$ python -m zipapp myapp -p "/usr/bin/env python"
$ ./myapp.pyz
<output from myapp>
要替换现有归档上的shebang行,请使用create_archive()
函数创建修改的归档:
>>> import zipapp
>>> zipapp.create_archive('old_archive.pyz', 'new_archive.pyz', '/usr/bin/python3')
要立即更新文件,请使用BytesIO
对象在内存中进行替换,然后再覆盖源。请注意,在覆盖文件时存在错误将导致原始文件丢失的风险。此代码不能防止此类错误,但生产代码应该这样做。此外,此方法将只有工作,如果存档适合内存:
>>> import zipapp
>>> import io
>>> temp = io.BytesIO()
>>> zipapp.create_archive('myapp.pyz', temp, '/usr/bin/python2')
>>> with open('myapp.pyz', 'wb') as f:
>>> f.write(temp.getvalue())
请注意,如果指定解释器,然后分发应用程序归档,则需要确保使用的解释器是可移植的。Windows的Python启动器支持POSIX #!
的最常见形式线,但还有其他问题需要考虑:
- 如果你使用“/ usr / bin / env python”(或其他形式的“python”命令,如“/ usr / bin / python”),你需要考虑你的用户可能有Python 2或Python 3作为它们的默认值,并且编写代码以在两个版本下工作。
- 如果您使用显式版本,例如“/ usr / bin / env python3”,您的应用程序将不适用于没有该版本的用户。(这可能是你想要的,如果你没有使你的代码Python 2兼容)。
- 没有办法说“python XY或更高版本”,所以要小心使用像“/ usr / bin / env python3.4”的确切版本,因为你需要为Python 3.5的用户更改你的shebang行,例如。
28.4.5. The Python Zip Application Archive Format¶
Python自2.6版本起就能够执行包含__main__.py
文件的zip文件。为了由Python执行,应用程序归档只需要是包含__main__.py
文件的标准zip文件,该文件将作为应用程序的入口点运行。与任何Python脚本一样,脚本的父代(在这种情况下为zip文件)将放置在sys.path
上,因此可以从zip文件导入更多模块。
zip文件格式允许将任意数据添加到zip文件。zip应用程序格式使用此功能在文件(#!/path/to/interpreter
)前面添加标准POSIX“shebang”行。
正式来说,Python zip应用程序格式是:
- 可选的shebang行,包含字符
b'#!'
后跟解释器名称,然后是换行符(b'\n'
)字符。解释器名称可以是OS“shebang”处理或Windows上的Python启动器可接受的任何名称。解释器应该在Windows上以UTF-8编码,在POSIX上在sys.getfilesystemencoding()
中编码。 - 标准zip文件数据,由
zipfile
模块生成。zip文件内容必须包含一个名为__main__.py
的文件(它必须位于zip文件的“根目录”中,即不能位于子目录中)。zipfile数据可以是压缩的或未压缩的。
如果应用程序归档具有shebang行,则它可以在POSIX系统上设置可执行位,以允许它直接执行。
没有要求该模块中的工具用于创建应用程序存档 - 该模块是方便的,但是通过任何方式创建的上述格式的存档都可以被Python接受。