Programmering

Sådan bruges PyInstaller til at oprette Python-eksekverbare filer

Python, kraftfuld og alsidig som den er, mangler et par nøglefunktioner ud af kassen. For det første giver Python ingen indbygget mekanisme til kompilering af et Python-program til en enkeltstående eksekverbar pakke.

For at være retfærdig krævede den originale brugssag til Python aldrig selvstændige pakker. Python-programmer er stort set kørt på plads på systemer, hvor en kopi af Python-tolken boede. Men den stigende popularitet af Python har skabt større efterspørgsel efter at køre Python-apps på systemer uden installeret Python-runtime.

Flere tredjeparter har konstrueret løsninger til implementering af uafhængige Python-apps. Den mest populære løsning af flokken, og den mest modne, er PyInstaller. PyInstaller gør ikke processen med at pakke en Python-app til at gå helt smertefri, men den går langt der.

I denne artikel udforsker vi det grundlæggende i brugen af ​​PyInstaller, herunder hvordan PyInstaller fungerer, hvordan man bruger PyInstaller til at oprette en uafhængig Python-eksekverbar, hvordan man finjusterer de Python-eksekverbare filer, du opretter, og hvordan man undgår nogle af de almindelige faldgruber, der går med brug af PyInstaller.

Oprettelse af en PyInstaller-pakke

PyInstaller er en Python-pakke, installeret med pip (pip install pyinstaller). PyInstaller kan installeres i din standard Python-installation, men det er bedst at oprette et virtuelt miljø til det projekt, du vil pakke, og installere PyInstaller der.

PyInstaller fungerer ved at læse dit Python-program, analysere al import, det laver, og bundte kopier af denne import med dit program. PyInstaller læser i dit program fra dets startpunkt. For eksempel, hvis dit programs indgangssted er myapp.py, ville du løbe pyinstaller myapp.py at udføre analysen. PyInstaller kan registrere og automatisk pakke mange almindelige Python-pakker, som NumPy, men du skal muligvis give tip i nogle tilfælde. (Mere om dette senere.)

Efter at have analyseret din kode og fundet alle de biblioteker og moduler, den bruger, genererer PyInstaller derefter en "spec-fil". Et Python-script med udvidelsen .spec, denne fil indeholder detaljer om, hvordan din Python-app skal pakkes op. Første gang du kører PyInstaller på din app, genererer PyInstaller en spec-fil fra bunden og udfylder den med nogle fornuftige standarder. Kassér ikke denne fil; det er nøglen til at raffinere en PyInstaller-implementering!

Endelig forsøger PyInstaller at producere en eksekverbar fil fra appen, bundtet med alle dens afhængigheder. Når den er færdig, navngives en undermappe dist (som standard kan du frit angive et andet navn) vises i projektmappen. Dette til gengæld indeholder en mappe, der er din medfølgende app - den har en .exe fil, der skal køres sammen med alle de nødvendige biblioteker og andre supplerende filer.

Alt hvad du skal gøre for at distribuere dit program er at pakke denne mappe op som en .zip fil eller et andet bundt. Pakken skal typisk ekstraheres i et bibliotek, hvor brugeren har skrivetilladelser for at køre.

Test af en PyInstaller-pakke

Der er en rimelig chance for, at dit første forsøg på at bruge PyInstaller til at pakke en app ikke vil være fuldstændig vellykket.

For at kontrollere, om din PyInstaller-pakke fungerer, skal du navigere til den mappe, der indeholder den medfølgende eksekverbare fil, og køre .exe fil der fra kommandolinjen. Hvis den ikke kører, skal de fejl, du ser udskrevet til kommandolinjen, give et tip til, hvad der er galt.

Den mest almindelige årsag til, at en PyInstaller-pakke mislykkes, er at PyInstaller ikke kunne samle en påkrævet fil. Sådanne manglende filer falder i nogle få kategorier:

  • Skjult eller manglende import: Nogle gange kan PyInstaller ikke registrere importen af ​​en pakke eller et bibliotek, typisk fordi det importeres dynamisk. Pakken eller biblioteket skal angives manuelt.
  • Manglende enkeltstående filer: Hvis programmet afhænger af eksterne datafiler, der skal bundtes med programmet, har PyInstaller ingen måde at vide det på. Du bliver nødt til at inkludere filerne manuelt.
  • Manglende binære filer: Her igen, hvis dit program afhænger af en ekstern binær som en .DLL, som PyInstaller ikke kan registrere, skal du manuelt inkludere den.

Den gode nyhed er, at PyInstaller giver en nem måde at håndtere ovenstående problemer på. Det .spec fil oprettet af PyInstaller inkluderer felter, som vi kan udfylde for at give de detaljer, som PyInstaller savnede.

Åbn .spec fil i en teksteditor og se efter definitionen af Analyse objekt. Flere af parametrene videregivet til Analyse er tomme lister, men de kan redigeres for at specificere de manglende detaljer:

  • skjultimport til skjult eller manglende import: Føj en eller flere strenge til denne liste med navnene på de biblioteker, du vil have med i din app. Hvis du vil tilføje pandaer og bokehfor eksempel ville du angive det som['pandaer', 'bokeh']. Bemærk, at de pågældende biblioteker skal installeres i samme forekomst af Python, hvor du kører PyInstaller.
  • datas for manglende uafhængige filer: Tilføj her en eller flere specifikationer for filer i dit projekttræ, som du vil medtage i dit projekt. Hver fil skal sendes som en tuple, der angiver den relative sti til filen i dit projektmappe og den relative sti i distributionsmappen, hvor du vil placere filen. For eksempel, hvis du havde en fil ./modeller/mainmodel.dat som du ville medtage i din app, og du vil placere den i en matchende underkatalog i din distributionsmappe, ville du bruge ('./models/mainmodel.dat','./models') som en post i skjultimport liste. Bemærk, at du kan bruge glob-stil jokertegn til at angive mere end en fil.
  • binære filer for manglende enkeltstående binære filer: Som med datas, du kan bruge binære filer at sende en liste over tupler, der specificerer placeringen af ​​binære filer i projekttræet og deres destinationer i distributionsmappen. Igen kan du bruge glob-stil jokertegn.

Husk, at nogen af ​​listerne sendes til Analyse kan genereres programmatisk tidligere i .spec fil. Når alt kommer til alt .spec filen er bare et Python-script med et andet navn.

Når du har foretaget ændringer i .spec fil, kør PyInstaller igen for at genopbygge pakken. Fra nu af skal du dog sørge for at videregive den modificerede .spec fil som parameter (f.eks. pyinstaller myapp.spec). Test den eksekverbare som før. Hvis noget stadig er i stykker, kan du redigere det .spec fil og gentag processen, indtil alt fungerer.

Endelig, når du er tilfreds, fungerer alt som beregnet, kan du redigere.spec fil for at forhindre, at din pakkede app præsenterer et kommandolinjevindue, når det startes. I EXE objektindstillinger i .spec fil, sætkonsol = falsk. Det er nyttigt at undertrykke konsollen, hvis din app har en GUI, og du ikke vil have et falsk kommandolinjevindue, der fører brugerne på afveje. Selvfølgelig skal du ikke ændre denne indstilling, hvis din app kræver en kommandolinje.

Forfining af en PyInstaller-pakke

Når du har pakket din app med PyInstaller og kører korrekt, er den næste ting, du sandsynligvis vil gøre, at slanke den lidt. PyInstaller-pakker er ikke kendt for at være svelte.

Fordi Python er et dynamisk sprog, er det svært at forudsige, hvad der er behov for ved kørsel af et givet program. Af den grund, når PyInstaller registrerer en pakkeimport, inkluderer den alt i den pakke, uanset om den faktisk bruges i løbet af dit program.

Her er de gode nyheder. PyInstaller inkluderer en mekanisme til selektivt at ekskludere hele pakker eller individuelle navneområder inden for pakker. Lad os f.eks. Sige, at dit program importerer pakke foo, Som indeholder foo.bar og foo.bip. Hvis du med sikkerhed ved, at dit program kun bruger logik ind foo.bar, kan du sikkert udelukke foo.bip og spar lidt plads.

For at gøre dette skal du bruge udelukker parameter videregivet til Analyse objekt i .spec fil. Du kan videregive en liste med navne - moduler på øverste niveau eller punkterede navneområder - for at ekskludere fra din pakke. For eksempel at ekskludere foo.bip, ville du blot angive['foo.bip'].

En almindelig udelukkelse, du kan foretage, er tkinter, Python-biblioteket til oprettelse af enkle grafiske brugergrænseflader på tværs af platforme. Som standard,tkinter og alle dens supportfiler er pakket med et PyInstaller-projekt. Hvis du ikke bruger tkinter i dit projekt kan du ekskludere det ved at tilføje 'tkinter' til udelukker liste. Udeladelse tkinter reducerer pakkens størrelse med omkring 7 MB.

En anden almindelig udelukkelse er testpakker. Hvis en pakke, som dit program importerer, har en testpakke, kan testpakke ende med at blive inkluderet i din PyInstaller-pakke. Medmindre du faktisk kører testpakken i dit implementerede program, kan du sikkert udelukke den.

Husk, at pakker, der er oprettet ved hjælp af undtagelser, skal testes grundigt, inden de bruges. Hvis du ender med at ekskludere funktionalitet, der bruges i et fremtidigt scenarie, som du ikke havde forventet, går din app i stykker.

Tips til PyInstaller

  • Byg din PyInstaller-pakke på det operativsystem, du planlægger at implementere på. PyInstaller understøtter ikke opbygning på tværs af platforme. Hvis du har brug for at installere din standalone Python-app på MacOS, Linux og Windows-systemer, skal du installere PyInstaller og oprette separate versioner af appen på hvert af disse operativsystemer.
  • Byg din PyInstaller-pakke, mens du udvikler din app. Så snart du ved, at du vil implementere dit projekt med PyInstaller, skal du bygge din .spec fil og start raffinering af PyInstaller-pakken parallelt med udviklingen af ​​din app. På denne måde kan du tilføje undtagelser eller indeslutninger, mens du går, og teste den måde, hvorpå nye funktioner implementeres i appen, mens du skriver dem.
  • Brug ikke PyInstaller's--onefile mode. PyInstaller inkluderer en kommandolinjekontakt, --onefile, der pakker hele din app i en enkelt selvudpakkende eksekverbar. Dette lyder som en god idé - du skal kun levere en fil! - men det har nogle faldgruber. Når du kører appen, skal den først udpakke alle filerne i den eksekverbare fil til et midlertidigt bibliotek. Hvis appen er stor (for eksempel 200 MB), kan udpakning betyde en forsinkelse på flere sekunder. Brug i stedet standardtilstanden for enkeltkatalog, og pak bare alt sammen som en .zip fil.
  • Opret et installationsprogram til din PyInstaller-app. Hvis du vil bruge en anden måde til at implementere din app end en .zip-fil, skal du overveje at bruge et installationsværktøj som det open source Nullsoft Scriptable Install System. Det tilføjer meget lidt overhead til størrelsen på den leverede og giver dig mulighed for at konfigurere mange aspekter af installationsprocessen, som at oprette genveje til din eksekverbare.
  • Forvent ikke speedups. PyInstaller er enemballage system, ikke etkompilatoreller enoptimering. Kode pakket med PyInstaller kører ikke hurtigere end den ville, når den køres på det originale system. Hvis du vil fremskynde Python-koden, skal du bruge et C-accelereret bibliotek, der passer til opgaven, eller et projekt som Cython.

Sådan gør du mere med Python

  • Cython tutorial: Sådan fremskyndes Python
  • Sådan installeres Python på den smarte måde
  • Bedre Python-projektstyring med Poetry
  • Virtualenv og venv: Python virtuelle miljøer forklaret
  • Python virtualenv og venv do's and don'ts
  • Python-gevind og underprocesser forklaret
  • Sådan bruges Python debugger
  • Sådan bruges timeit til at profilere Python-kode
  • Sådan bruges cProfile til profilering af Python-kode
  • Kom godt i gang med async i Python
  • Sådan bruges asyncio i Python
  • Sådan konverteres Python til JavaScript (og tilbage igen)