Movatterモバイル変換


[0]ホーム

URL:


Following system colour schemeSelected dark colour schemeSelected light colour scheme

Python Enhancement Proposals

PEP 441 – Improving Python ZIP Application Support

Author:
Daniel Holth <dholth at gmail.com>,Paul Moore <p.f.moore at gmail.com>
Discussions-To:
Python-Dev message
Status:
Final
Type:
Standards Track
Created:
30-Mar-2013
Python-Version:
3.5
Post-History:
30-Mar-2013, 01-Apr-2013, 16-Feb-2015
Resolution:
Python-Dev message

Table of Contents

Improving Python ZIP Application Support

Python has had the ability to execute directories or ZIP-formatarchives as scripts since version 2.6[1]. When invoked with a zipfile or directory as its first argument the interpreter adds thatdirectory to sys.path and executes the__main__ module. Thesearchives provide a great way to publish software that needs to bedistributed as a single file script but is complex enough to need tobe written as a collection of modules.

This feature is not as popular as it should be mainly because it wasnot promoted as part of Python 2.6[2], so that it is relativelyunknown, but also because the Windows installer does not register afile extension (other than.py) for this format of file, to associatewith the launcher.

This PEP proposes to fix these problems by re-publicising the feature,defining the.pyz and.pyzw extensions as “Python ZIP Applications”and “Windowed Python ZIP Applications”, and providing some simpletooling to manage the format.

A New Python ZIP Application Extension

The terminology “Python Zip Application” will be the formal term usedfor a zip-format archive that contains Python code in a form that canbe directly executed by Python (specifically, it must have a__main__.py file in the root directory of the archive). Theextension.pyz will be formally associated with such files.

The Python 3.5 installer will associate.pyz and.pyzw “PythonZip Applications” with the platform launcher so they can be executed.A.pyz archive is a console application and a.pyzw archive is awindowed application, indicating whether the console should appearwhen running the app.

On Unix, it would be ideal if the.pyz extension and the name“Python Zip Application” were registered (in the mime types database?).However, such an association is out of scope for this PEP.

Python Zip applications can be prefixed with a#! linepointing to the correct Python interpreter and an optionalexplanation:

#!/usr/bin/env python3#  Python application packed with zipapp module(binarycontentsofarchive)

On Unix, this allows the OS to run the file with the correctinterpreter, via the standard “shebang” support. On Windows, thePython launcher implements shebang support.

However, it is always possible to execute a.pyz application bysupplying the filename to the Python interpreter directly.

As background, ZIP archives are defined with a footer containingrelative offsets from the end of the file. They remain valid whenconcatenated to the end of any other file. This feature is completelystandard and is how self-extracting ZIP archives and the bdist_wininstinstaller format work.

Minimal Tooling: The zipapp Module

This PEP also proposes including a module for working with thesearchives. The module will contain functions for working with Pythonzip application archives, and a command line interface (viapython-mzipapp) for their creation and manipulation.

More complete tools for managing Python Zip Applications areencouraged as 3rd party applications on PyPI. Currently, pyzzer[5]and pex[6] are two such tools.

Module Interface

The zipapp module will provide the following functions:

create_archive(source,target=None,interpreter=None,main=None)

Create an application archive fromsource. The source can be anyof the following:

  • The name of a directory, in which case a new application archivewill be created from the content of that directory.
  • The name of an existing application archive file, in which case thefile is copied to the target. The file name should include the.pyz or.pyzw extension, if required.
  • A file object open for reading in bytes mode. The content of thefile should be an application archive, and the file object isassumed to be positioned at the start of the archive.

Thetarget argument determines where the resulting archive will bewritten:

  • If it is the name of a file, the archive will be written to thatfile.
  • If it is an open file object, the archive will be written to thatfile object, which must be open for writing in bytes mode.
  • If the target is omitted (or None), the source must be a directoryand the target will be a file with the same name as the source, witha.pyz extension added.

Theinterpreter argument specifies the name of the Pythoninterpreter with which the archive will be executed. It is written asa “shebang” line at the start of the archive. On Unix, this will beinterpreted by the OS, and on Windows it will be handled by the Pythonlauncher. Omitting theinterpreter results in no shebang line beingwritten. If an interpreter is specified, and the target is afilename, the executable bit of the target file will be set.

Themain argument specifies the name of a callable which will beused as the main program for the archive. It can only be specified ifthe source is a directory, and the source does not already contain a__main__.py file. Themain argument should take the form“pkg.module:callable” and the archive will be run by importing“pkg.module” and executing the given callable with no arguments. Itis an error to omitmain if the source is a directory and does notcontain a__main__.py file, as otherwise the resulting archivewould not be executable.

If a file object is specified forsource ortarget, it is thecaller’s responsibility to close it after calling create_archive.

When copying an existing archive, file objects supplied only needread andreadline, orwrite methods. When creating anarchive from a directory, if the target is a file object it will bepassed to thezipfile.ZipFile class, and must supply the methodsneeded by that class.

get_interpreter(archive)

Returns the interpreter specified in the shebang line of thearchive. If there is no shebang, the function returnsNone.Thearchive argument can be a filename or a file-like object openfor reading in bytes mode.

Command Line Usage

The zipapp module can be run with the python-m flag. The commandline interface is as follows:

python-mzipappdirectory[options]Createanarchivefromthegivendirectory.Anarchivewillbecreatedfromthecontentsofthatdirectory.Thearchivewillhavethesamenameasthesourcedirectorywitha.pyzextension.Thefollowingoptionscanbespecified:-oarchive/--outputarchiveThedestinationarchivewillhavethespecifiedname.Thegivennamewillbeusedaswritten,soshouldincludethe".pyz"or".pyzw"extension.-pinterpreter/--pythoninterpreterThegiveninterpreterwillbewrittentotheshebanglineofthearchive.Ifthisoptionisnotgiven,thearchivewillhavenoshebangline.-mpkg.mod:fn/--mainpkg.mod:fnThesourcedirectorymustnothavea__main__.pyfile.Thearchiverwillwritea__main__.pyfileintothetargetwhichcallsfnfromthemodulepkg.mod.

The behaviour of the command line interface matches that ofzipapp.create_archive().

In addition, it is possible to use the command line interface to workwith an existing archive:

python-mzipappapp.pyz--showDisplaystheshebanglineofanarchive.OutputisoftheformInterpreter:/usr/bin/envorInterpreter:<none>andisintendedfordiagnosticuse,notforscripts.python-mzipappapp.pyz-onewapp.pyz[-pinterpreter]Copyapp.pyztonewapp.pyz,modifyingtheshebanglinebasedonthe-poption(asforcreatinganarchive,no-poptionmeansremovetheshebangline).Specifyingadestinationismandatory.In-placemodificationofanarchiveis*not*supported,astheriskofdamagingarchivesistoogreatforasimpletool.

As noted, the archives are standard zip files, and so can be unpackedusing any standard ZIP utility or Python’s zipfile module. For thisreason, no interfaces to list the contents of an archive, or unpackthem, are provided or needed.

FAQ

Are you sure a standard ZIP utility can handle#! at the beginning?
Absolutely. The zipfile specification allows for arbitrary data tobe prepended to a zipfile. This feature is commonly used by“self-extracting zip” programs. If your archive program can’thandle this, it is a bug in your archive program.
Isn’t zipapp just a very thin wrapper over the zipfile module?
Yes. If you prefer to build your own Python zip applicationarchives using other tools, they will work just as well. Thezipapp module is a convenience, nothing more.
Why not use just use a.zip or.py extension?
Users expect a.zip file to be opened with an archive tool, andexpect a.py file to contain readable text. Both would beconfusing for this use case.
How does this compete with existing package formats?
The sdist, bdist and wheel formats are designed for packaging ofmodules to be installed into an existing Python installation.They are not intended to be used without installing. Theexecutable zip format is specifically designed for standalone use,without needing to be installed. They are in effect a multi-fileversion of a standalone Python script.

Rejected Proposals

Convenience Values for Shebang Lines

Is it worth having “convenience” forms for any of the commoninterpreter values? For example,-p3 meaning the same as-p"/usr/bin/envpython3". It would save a lot of typing for thecommon cases, as well as giving cross-platform options for people whodon’t want or need to understand the intricacies of shebang handlingon “other” platforms.

Downsides are that it’s not obvious how to translate theabbreviations. For example, should “3” mean “/usr/bin/env python3”,“/usr/bin/python3”, “python3”, or something else? Also, there is noobvious short form for the key case of “/usr/bin/env python” (anyavailable version of Python), which could easily result in scriptsbeing written with overly-restrictive shebang lines.

Overall, this seems like there are more problems than benefits, and asa result has been dropped from consideration.

Registering.pyz as a Media Type

It was suggested[3] that the.pyz extension should be registeredin the Unix database of extensions. While it makes sense to do thisas an equivalent of the Windows installer registering the extension,the.py extension is not listed in the media types database[4].It doesn’t seem reasonable to register.pyz without.py, sothis idea has been omitted from this PEP. An interested party couldarrange forboth.py and.pyz to be registered at a futuredate.

Default Interpreter

The initial draft of this PEP proposed using/usr/bin/envpythonas the default interpreter. Unix users have problems with thisbehaviour, as the default for the python command on many distributionsis Python 2, and it is felt that this PEP should prefer Python 3 bydefault. However, using a command ofpython3 can result inunexpected behaviour for Windows users, where the default behaviour ofthe launcher for the commandpython is commonly customised by users,but the behaviour ofpython3 may not be modified to match.

As a result, the principle “in the face of ambiguity, refuse to guess”has been invoked, and archives have no shebang line unless explicitlyrequested. On Windows, the archives will still be run (with thedefault Python) by the launcher, and on Unix, the archives can be runby explicitly invoking the desired Python interpreter.

Command Line Tool to Manage Shebang Lines

It is conceivable that users would want to modify the shebang line foran existing archive, or even just display the current shebang line.This is tricky to do so with existing tools (zip programs typicallyignore prepended data totally, and text editors can have troubleediting files containing binary data).

The zipapp module provides functions to handle the shebang line, butdoes not include a command line interface to that functionality. Thisis because it is not clear how to provide one without the resultinginterface being over-complex and potentially confusing. Changing theshebang line is expected to be an uncommon requirement.

Reference Implementation

A reference implementation is athttp://bugs.python.org/issue23491.

References

[1]
Allow interpreter to execute a zip file(http://bugs.python.org/issue1739468)
[2]
Feature is not documented(http://bugs.python.org/issue17359)
[3]
Discussion of adding a .pyz mime type on python-dev(https://mail.python.org/pipermail/python-dev/2015-February/138338.html)
[4]
Register of media types(http://www.iana.org/assignments/media-types/media-types.xhtml)
[5]
pyzzer - A tool for creating Python-executable archives(https://pypi.python.org/pypi/pyzzer)
[6]
pex - The PEX packaging toolchain(https://pypi.python.org/pypi/pex)

The discussion of this PEP took place on the python-dev mailing list,in the thread starting athttps://mail.python.org/pipermail/python-dev/2015-February/138277.html

Copyright

This document has been placed into the public domain.


Source:https://github.com/python/peps/blob/main/peps/pep-0441.rst

Last modified:2025-02-01 08:55:40 GMT


[8]ページ先頭

©2009-2025 Movatter.jp