zipapp
— Hantera körbara Python zip-arkiv¶
Tillagd i version 3.5.
Källkod: Lib/zipapp.py
Den här modulen tillhandahåller verktyg för att hantera skapandet av zip-filer som innehåller Python-kod, som kan exekveras direkt av Python-tolken. Modulen tillhandahåller både ett Kommandoradsgränssnitt och ett Python API.
Grundläggande exempel¶
Följande exempel visar hur Kommandoradsgränssnitt kan användas för att skapa ett körbart arkiv från en katalog som innehåller Python-kod. När arkivet körs kommer det att exekvera funktionen main
från modulen myapp
i arkivet.
$ python -m zipapp myapp -m "myapp:main"
$ python myapp.pyz
<output from myapp>
Kommandoradsgränssnitt¶
När ett program anropas från kommandoraden används följande form:
$ python -m zipapp källa [alternativ]
Om källa är en katalog skapas ett arkiv från innehållet i källa. Om källa är en fil bör den vara ett arkiv och kopieras till målarkivet (eller så visas innehållet i dess shebang-rad om alternativet –info har angetts).
Följande alternativ är möjliga:
- -o <output>, --output=<output>¶
Skriv utdata till en fil med namnet output. Om detta alternativ inte anges kommer filnamnet för utdata att vara detsamma som för indata källa, med tillägget
.pyz
. Om ett explicit filnamn anges används det som det är (så ett tillägg.pyz
bör inkluderas om så krävs).Ett filnamn för utdata måste anges om källan är ett arkiv (och i så fall får utdata inte vara samma som källan).
- -p <interpreter>, --python=<interpreter>¶
Lägg till en rad med
#!
i arkivet och ange tolken som kommando som ska köras. På POSIX måste du också göra arkivet körbart. Standardinställningen är att inte skriva någon rad med#!
och att inte göra filen körbar.
- -m <mainfn>, --main=<mainfn>¶
Skriv en fil med namnet
__main__.py
till arkivet som kör mainfn. Argumentet mainfn ska ha formen ”pkg.mod:fn”, där ”pkg.mod” är ett paket/en modul i arkivet och ”fn” är en anropbar funktion i den givna modulen. Filen__main__.py
kommer att exekvera den anropbara filen.--main
kan inte anges vid kopiering av ett arkiv.
- -c, --compress¶
Komprimera filer med deflate-metoden, vilket minskar storleken på utdatafilen. Som standard lagras filerna okomprimerade i arkivet.
--compress
har ingen effekt vid kopiering av ett arkiv.Tillagd i version 3.7.
- --info¶
Visar tolken som är inbäddad i arkivet, för diagnostiska ändamål. I det här fallet ignoreras alla andra alternativ och SOURCE måste vara ett arkiv, inte en katalog.
- -h, --help¶
Skriv ut ett kort användarmeddelande och avsluta.
Python API¶
Modulen definierar två bekvämlighetsfunktioner:
- zipapp.create_archive(source, target=None, interpreter=None, main=None, filter=None, compressed=False)¶
Skapa ett applikationsarkiv från källa. Källan kan vara något av följande:
Namnet på en katalog, eller ett path-like object som hänvisar till en katalog, i vilket fall ett nytt applikationsarkiv skapas från innehållet i den katalogen.
Namnet på en befintlig applikationsarkivfil eller ett path-like object som hänvisar till en sådan fil, varvid filen kopieras till målet (och ändras så att den återspeglar det värde som anges för argumentet interpreter). Filnamnet bör innehålla tillägget
.pyz
, om så krävs.Ett filobjekt som är öppet för läsning i bytesläge. Filens innehåll bör vara ett applikationsarkiv, och filobjektet antas vara placerat i början av arkivet.
Argumentet target bestämmer var det resulterande arkivet ska skrivas:
Om det är namnet på en fil, eller ett path-like object, skrivs arkivet till den filen.
Om det är ett öppet filobjekt kommer arkivet att skrivas till det filobjektet, som måste vara öppet för skrivning i bytesläge.
Om målet utelämnas (eller
None
) måste källan vara en katalog och målet kommer att vara en fil med samma namn som källan, med tillägget.pyz
.
Argumentet interpreter anger namnet på den Python-tolk som arkivet ska köras med. Det skrivs som en ”shebang”-rad i början av arkivet. På POSIX tolkas detta av operativsystemet, och på Windows hanteras det av Python-startprogrammet. Om tolk utelämnas skrivs ingen shebang-rad. Om en tolk anges och målet är ett filnamn, kommer den körbara biten i målfilen att sättas.
Argumentet main anger namnet på en anropbar fil som kommer att användas som huvudprogram för arkivet. Det kan bara anges om källan är en katalog och om källan inte redan innehåller en fil med namnet
__main__.py
. Argumentet main bör ha formen ”pkg.module:callable” och arkivet kommer att köras genom att importera ”pkg.module” och köra den angivna callable utan argument. Det är ett fel att utelämna main om källan är en katalog och inte innehåller filen__main__.py
, eftersom det resulterande arkivet annars inte skulle vara körbart.Det valfria argumentet filter anger en callback-funktion som får ett Path-objekt som representerar sökvägen till den fil som ska läggas till (i förhållande till källkatalogen). Den ska returnera
True
om filen ska läggas till.Det valfria argumentet compressed avgör om filerna ska komprimeras. Om värdet är
True
komprimeras filerna i arkivet med deflate-metoden, annars lagras filerna okomprimerade. Detta argument har ingen effekt vid kopiering av ett befintligt arkiv.Om ett filobjekt anges för source eller target är det anroparens ansvar att stänga det efter anropet av create_archive.
Vid kopiering av ett befintligt arkiv behöver filobjekt som levereras endast metoderna
read
ochreadline
ellerwrite
. När du skapar ett arkiv från en katalog, om målet är ett filobjekt, kommer det att skickas till klassenzipfile.ZipFile
, och måste tillhandahålla de metoder som behövs av den klassen.Ändrad i version 3.7: Parametrarna filter och compressed har lagts till.
Exempel¶
Packa ihop en katalog till ett arkiv och kör det.
$ python -m zipapp myapp
$ python myapp.pyz
<output from myapp>
Samma sak kan göras med hjälp av funktionen create_archive()
:
>>> import zipapp
>>> zipapp.create_archive('myapp', 'myapp.pyz')
Om du vill att programmet ska kunna köras direkt på POSIX anger du en tolk som ska användas.
$ python -m zipapp myapp -p "/usr/bin/env python"
$ ./myapp.pyz
<output from myapp>
För att ersätta shebang-raden i ett befintligt arkiv, skapa ett modifierat arkiv med hjälp av create_archive()
-funktionen:
>>> import zipapp
>>> zipapp.create_archive('old_archive.pyz', 'new_archive.pyz', '/usr/bin/python3')
Om du vill uppdatera filen på plats gör du ersättningen i minnet med hjälp av ett BytesIO
-objekt och skriver sedan över källan efteråt. Observera att det finns en risk när du skriver över en fil på plats att ett fel leder till att originalfilen går förlorad. Den här koden skyddar inte mot sådana fel, men produktionskoden bör göra det. Dessutom fungerar denna metod endast om arkivet ryms i memory:
>>> 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())
Specificering av tolkprogrammet¶
Observera att om du anger en tolk och sedan distribuerar ditt programarkiv måste du se till att den tolk som används är portabel. Python-startprogrammet för Windows stöder de vanligaste formerna av POSIX #!
-raden, men det finns andra problem att ta hänsyn till:
Om du använder ”/usr/bin/env python” (eller andra former av kommandot ”python”, till exempel ”/usr/bin/python”) måste du tänka på att dina användare kan ha antingen Python 2 eller Python 3 som standard, och skriva din kod så att den fungerar under båda versionerna.
Om du använder en explicit version, t.ex. ”/usr/bin/env python3”, kommer din applikation inte att fungera för användare som inte har den versionen. (Detta kan vara vad du vill om du inte har gjort din kod Python 2-kompatibel).
Det finns inget sätt att säga ”python X.Y eller senare”, så var försiktig med att använda en exakt version som ”/usr/bin/env python3.4” eftersom du kommer att behöva ändra din shebang-rad för användare av Python 3.5, till exempel.
Vanligtvis bör du använda en ”/usr/bin/env python2” eller ”/usr/bin/env python3”, beroende på om din kod är skriven för Python 2 eller 3.
Skapa fristående program med zipapp¶
Med modulen zipapp
är det möjligt att skapa självständiga Python-program som kan distribueras till slutanvändare som bara behöver ha en lämplig version av Python installerad på sitt system. Nyckeln till att göra detta är att paketera alla applikationens beroenden i arkivet, tillsammans med applikationskoden.
Så här går du tillväga för att skapa ett fristående arkiv:
Skapa din applikation i en katalog som vanligt, så att du har en katalog med namnet
myapp
som innehåller en fil med namnet__main__.py
och all stödjande applikationskod.Installera alla beroenden för din applikation i katalogen
myapp
med hjälp av pip:$ python -m pip install -r requirements.txt --target myapp
(detta förutsätter att du har dina projektkrav i en fil
requirements.txt
- om inte, kan du bara lista beroendena manuellt på pip-kommandoraden).Paketera ansökan med hjälp av:
$ python -m zipapp -p "tolk" myapp
Detta ger en fristående körbar fil som kan köras på vilken maskin som helst med lämplig tolk tillgänglig. Se Specificering av tolkprogrammet för mer information. Den kan skickas till användare som en enda fil.
På Unix är filen myapp.pyz
körbar som den är. Du kan byta namn på filen så att tillägget .pyz
tas bort om du föredrar ett ”vanligt” kommandonamn. På Windows är filen myapp.pyz[w]
körbar eftersom Python-tolken registrerar filtilläggen .pyz
och .pyzw
när den installeras.
Förbehåll¶
Om ditt program är beroende av ett paket som innehåller ett C-tillägg kan det paketet inte köras från en zip-fil (detta är en OS-begränsning, eftersom körbar kod måste finnas i filsystemet för att OS-laddaren ska kunna ladda den). I det här fallet kan du utesluta det beroendet från zip-filen och antingen kräva att dina användare har det installerat, eller skicka det tillsammans med din zip-fil och lägga till kod i din __main__.py
för att inkludera katalogen som innehåller den uppackade modulen i sys.path
. I det här fallet måste du se till att leverera lämpliga binärfiler för din målarkitektur (och eventuellt välja rätt version att lägga till i sys.path
vid körning, baserat på användarens maskin).
Python Zip Application Arkivformat¶
Python har kunnat exekvera zip-filer som innehåller filen __main__.py
sedan version 2.6. För att kunna köras av Python måste ett applikationsarkiv helt enkelt vara en standard zip-fil som innehåller filen __main__.py
som kommer att köras som startpunkt för applikationen. Som vanligt för alla Python-skript kommer skriptets överordnade fil (i det här fallet zip-filen) att placeras på sys.path
och därmed kan ytterligare moduler importeras från zip-filen.
Med zip-filformatet kan godtyckliga data prependlas till en zip-fil. Zip-applikationsformatet använder denna möjlighet för att lägga till en standard POSIX ”shebang”-rad till filen (#!/path/to/interpreter
).
Formellt är Python zip-applikationsformatet därför:
En valfri shebang-rad som innehåller tecknen
b'#!'
följt av ett tolknamn och sedan ett nytt radtecken (b'\n'
). Tolknamnet kan vara vad som helst som är acceptabelt för OS:ets ”shebang”-behandling eller Python-startprogrammet i Windows. Tolken bör kodas i UTF-8 på Windows, och isys.getfilesystemencoding()
på POSIX.Standard zipfile-data, som genereras av modulen
zipfile
. Innehållet i zipfilen måste innehålla en fil som heter__main__.py
(som måste ligga i ”roten” av zipfilen - dvs. den kan inte ligga i en underkatalog). Zipfilens data kan vara komprimerad eller okomprimerad.
Om ett programarkiv har en shebang-rad kan den ha den exekverbara biten inställd på POSIX-system, så att den kan köras direkt.
Det finns inget krav på att verktygen i denna modul används för att skapa applikationsarkiv - modulen är en bekvämlighet, men arkiv i ovanstående format som skapats på något sätt är acceptabla för Python.