Paketera en Python-applikation med dess beroenden
För en tid sedan utvecklade jag en applikation i Python. För att ställa in sammanhanget handlade det om att skapa en körbar fil som kunde distribuera en docker-compose.yml genom att tillämpa affärsregler. För att inte skriva om allt skapade jag ett projekt i Python för att kunna använda biblioteket docker-compose som också finns i Python. När min applikation väl fungerade måste den byggas i en enda fil. Mitt mål var att generera en binär fil inklusive alla dess beroenden (lite som Golang).
Uppmärksamhet! Att generera en binär fil fritar dig inte från att installera Python på din maskin. Den binära filen är inte ett kompilerat program utan bara ett paket.
arkitektur
Först skapar du en mapp Foo bar i ditt projekt. Detta kommer att innehålla allt ditt arbete.
1
2
3
4
5
6
|
projektet
|_ __main__.py
|_ foobar
|_ __init__.py
|_ __main__.py
|_cli.py
|
Om du stött på den här artikeln beror det på att du kan Python minst lika bra som jag och därför vet hur du installerar beroenden globalt eller i en virtualenv.
Personligen genomför jag mina utvecklingar inom en Docker-container så jag installerar mina beroenden som globala.
Så här installerar du ett beroende.
1
|
$ pip installera docopt
|
Sedan kan du arbeta med din fil cli.py. Här är ett exempel på användningen av biblioteket docpt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# project/foobar/cli.py
från docpt importera docpt
släpp = "1.0.0"
hjälp = " " "Foo bar
Användning:
foobar version
Alternativ:
-h --help Visa hjälp
Foobar är ett falskt open source-projekt utvecklat av Baptiste Donaux.
"" "
def huvudsakliga():
argument = docopt(hjälp)
if argument["version"]:
skriva ut("foobar version", version)
|
En fil för att starta utvecklingsapplikationen kommer att behövas (i mitt fall __init__.py är en tom men obligatorisk fil).
1
2
3
4
5
6
|
# project/foobar/__main__.py
från . importera cli
if __namn__ == "__hand__":
cli.main()
|
För att bygga ett binärt paket behöver du en ingångspunkt (project/__main__.py).
1
2
3
4
5
6
|
# project/__main__.py
från Foo bar importera cli
if __namn__ == "__hand__":
cli.main()
|
Nu kan du enkelt köra din applikation.
1
2
|
$ python ./foobar/version
('foobar version', '1.0.0')
|
Bygg en statisk binär
Arbetsflöde
Från ett rent projekt (utan beroende...), här är stegen som kommer att utföras.
- Att skapa en virtualenv och aktivera den
- Installera beroenden och avsluta virtualenv
- Ta bort filer och mappar som finns i virtualenv/lib/python2.7/sites-packages som motsvarar en mapp pip, en cachemapp, till kompilerade filer eller informationsfiler.
- Skapa en mapp för att bygga den slutliga filen
- Kopiera beroenden, källor och indatafil till den nyskapade mappen.
- Skapa en komprimerad mapp (. Zip) av innehållet i byggmappen.
- Skapa den "binära" filen med en rubrik för att specificera miljön och lägg till den här filen innehållet i den komprimerade mappen.
Hardcore
Här är de tekniska stegen att följa.
1
2
3
4
5
6
7
8
9
10
11
12
|
$ virtualenv beroenden
$. ./dependencies/bin/activate
$ pip installera docopt
$ avaktivera
$ rm -rf $(hitta ./dependencies/lib/python2.7/site-packages -print | egrep '(/pip/)|(__pycache__)|(.(pyc|dist-info|so)$)')
$ mkdir bygga
$ cp -R ./dependencies/lib/python2.7/site-packages/* ./foobar ./__main__.py ./build/
$ cd ./bygga
$ zip -r ../release.zip *
$ missar '#!/usr/bin/env python' > ../släpp
$ cat ../release.zip >> ../release
$ chmod +x ../release
|
Slutsats
Nu kan du enkelt köra din binära fil. Den bäddar in hela sitt sammanhang.
1
2
|
$ ./release version
('foobar version', '1.0.0')
|
Den här lösningen var väldigt bekväm för mig att distribuera ett program med en enda fil. Du kan ladda ner exempelfilarkivet för att återskapa min demonstration.