Python, potente e versatile come è, manca di alcune funzionalità chiave fuori dalla scatola. Per uno, Python non fornisce alcun meccanismo nativo per la compilazione di un programma Python in un pacchetto eseguibile autonomo.

Per essere onesti, il caso d’uso originale per Python non ha mai richiesto pacchetti standalone. I programmi Python sono, in generale, stati eseguiti sul posto su sistemi in cui viveva una copia dell’interprete Python. Ma la crescente popolarità di Python ha creato una maggiore domanda per l’esecuzione di applicazioni Python su sistemi senza runtime Python installato.,

Diverse terze parti hanno progettato soluzioni per la distribuzione di app Python standalone. La soluzione più popolare del gruppo, e la più matura, è PyInstaller. PyInstaller non rende il processo di confezionamento di un’app Python totalmente indolore, ma fa molta strada.

In questo articolo esploreremo le basi dell’utilizzo di PyInstaller incluso come funziona PyInstaller, come utilizzare PyInstaller per creare un eseguibile Python autonomo, come mettere a punto gli eseguibili Python creati e come evitare alcune delle insidie comuni che accompagnano l’utilizzo di PyInstaller.,

Creazione di un pacchetto PyInstaller

PyInstaller è un pacchetto Python, installato conpip (pip install pyinstaller). PyInstaller può essere installato nell’installazione Python predefinita, ma è meglio creare un ambiente virtuale per il progetto che si desidera impacchettare e installare PyInstaller lì.

PyInstaller funziona leggendo il tuo programma Python, analizzando tutte le importazioni che produce e raggruppando copie di tali importazioni con il tuo programma. PyInstaller legge nel tuo programma dal suo punto di ingresso., Ad esempio, se il punto di ingresso del programma è myapp.py, eseguire pyinstaller myapp.py per eseguire l’analisi. PyInstaller può rilevare e confezionare automaticamente molti pacchetti Python comuni, come NumPy, ma potrebbe essere necessario fornire suggerimenti in alcuni casi. (Più su questo più tardi.)

Dopo aver analizzato il codice e scoperto tutte le librerie e i moduli utilizzati, PyInstaller genera quindi un ” file spec.”Uno script Python con estensione .spec, questo file include dettagli su come la tua app Python deve essere imballata., La prima volta che esegui PyInstaller sulla tua app, PyInstaller genererà un file spec da zero e lo popolerà con alcune impostazioni predefinite sane. Non scartare questo file; è la chiave per perfezionare una distribuzione di PyInstaller!

Infine, PyInstaller tenta di produrre un eseguibile dall’app, in bundle con tutte le sue dipendenze. Al termine, una sottocartella denominata dist (per impostazione predefinita, sei libero di specificare un nome diverso) apparirà nella directory del progetto., Questo a sua volta contiene una directory che è la tua app in bundle-ha un file.exe da eseguire, insieme a tutte le librerie e altri file supplementari richiesti.

Tutto quello che devi fare per distribuire il tuo programma, quindi, è impacchettare questa directory come un file .zip o qualche altro pacchetto. In genere, il bundle deve essere estratto in una directory in cui l’utente dispone di autorizzazioni di scrittura per l’esecuzione.

IDG

A .spec file viene utilizzato per creare un eseguibile con PyInstaller., Nota gli spazi dei nomi elencati in excludes. Questi saranno lasciati fuori dal pacchetto creato per risparmiare spazio.

Test di un pacchetto PyInstaller

C’è una buona probabilità che il tuo primo tentativo di utilizzare PyInstaller per confezionare un’app non abbia successo.

Per verificare se il pacchetto PyInstaller funziona, passare alla directory contenente l’eseguibile in bundle ed eseguire il file .exe dalla riga di comando., Se non riesce a funzionare, gli errori che vedrai stampati sulla riga di comando dovrebbero fornire un suggerimento su cosa c’è che non va.

Il motivo più comune per cui un pacchetto PyInstaller fallisce è che PyInstaller non è riuscito a raggruppare un file richiesto. Tali file mancanti rientrano in alcune categorie:

  • Importazioni nascoste o mancanti: a volte PyInstaller non può rilevare l’importazione di un pacchetto o di una libreria, in genere perché viene importato dinamicamente. Il pacchetto o la libreria dovranno essere specificati manualmente.,
  • File standalone mancanti: se il programma dipende da file di dati esterni che devono essere forniti in bundle con il programma, PyInstaller non ha modo di saperlo. Avrete bisogno di includere manualmente i file.
  • Binari mancanti: anche in questo caso, se il tuo programma dipende da un binario esterno come a .DLL che PyInstaller non può rilevare, è necessario includerlo manualmente.

La buona notizia è che PyInstaller fornisce un modo semplice per affrontare i problemi di cui sopra., Il file.spec creato da PyInstaller include campi che possiamo compilare per fornire i dettagli che PyInstaller ha perso.

Aprire il file.spec in un editor di testo e cercare la definizione dell’oggettoAnalysis. Molti dei parametri passati aAnalysis sono liste vuote, ma possono essere modificati per specificare i dettagli mancanti:

  • hiddenimports per le importazioni nascoste o mancanti: Aggiungi a questo elenco una o più stringhe con i nomi delle librerie che vuoi includere con la tua app., Se si desidera aggiungere pandasebokeh, ad esempio, è necessario specificarlo come. Si noti che le librerie in questione devono essere installate nella stessa istanza di Python in cui si sta eseguendo PyInstaller.
  • datas per i file standalone mancanti: aggiungi qui una o più specifiche per i file nell’albero del progetto che vuoi includere nel tuo progetto., Ogni file deve essere passato come una tupla che indica il percorso relativo al file nella directory del progetto e il percorso relativo all’interno della directory di distribuzione in cui si desidera posizionare il file. Ad esempio, se hai un file ./models/mainmodel.dat che vuoi includere con la tua app e vuoi inserirlo in una sottodirectory corrispondente nella tua directory di distribuzione, useresti ('./models/mainmodel.dat','./models') come una voce nell’elenco hiddenimports. Si noti che è possibile utilizzare i caratteri jollyglobper specificare più di un file.,
  • binaries per i binari standalone mancanti: Come con datas, è possibile utilizzare binaries per passare un elenco di tuple che specificano le posizioni dei binari nell’albero del progetto e le loro destinazioni nella directory di distribuzione. Ancora una volta, è possibile utilizzare glob-stile jolly.

Tieni presente che qualsiasi lista passata aAnalysis può essere generata a livello di codice in precedenza nel file.spec., Dopo tutto, il file .spec è solo uno script Python con un altro nome.

Dopo aver apportato modifiche al file.spec, eseguire nuovamente PyInstaller per ricostruire il pacchetto. Tuttavia, d’ora in poi, assicurati di passare il file .spec modificato come parametro (ad esempio pyinstaller myapp.spec). Prova l’eseguibile come prima. Se qualcosa è ancora rotto, è possibile modificare nuovamente il file .spec e ripetere il processo fino a quando tutto funziona.,

Infine, quando sei soddisfatto che tutto funzioni come previsto, potresti voler modificare il file.spec per impedire che la tua app pacchettizzata presenti una finestra della riga di comando quando viene avviata. Nelle impostazioni dell’oggettoEXE nel file.spec, impostareconsole=False. La soppressione della console è utile se la tua app ha una GUI e non vuoi una finestra della riga di comando spuria che porta gli utenti fuori strada. Ovviamente, non modificare questa impostazione se la tua app richiede una riga di comando.,

Raffinazione di un pacchetto PyInstaller

Una volta che hai la tua app impacchettata con PyInstaller e funzionante correttamente, la prossima cosa che probabilmente vorrai fare è snellirla un po’. I pacchetti PyInstaller non sono noti per essere svelte.

Poiché Python è un linguaggio dinamico, è difficile prevedere solo ciò che sarà necessario in fase di runtime da un determinato programma. Per questo motivo, quando PyInstaller rileva un’importazione di pacchetti, include tutto in quel pacchetto, indipendentemente dal fatto che sia effettivamente utilizzato in fase di runtime dal programma.

Ecco la buona notizia., PyInstaller include un meccanismo per escludere selettivamente interi pacchetti o singoli spazi dei nomi all’interno dei pacchetti. Ad esempio, supponiamo che il tuo programma importi il pacchetto foo, che include foo.bar e foo.bip. Se sai per certo che il tuo programma usa solo la logica in foo.bar, puoi tranquillamente escludere foo.bip e risparmiare spazio.

Per fare ciò, si utilizza il parametro excludes passato all’oggetto Analysis nel file .spec., È possibile passare un elenco di nomi-moduli di primo livello o spazi dei nomi punteggiati-da escludere dal pacchetto. Ad esempio, per escludere foo.bip, è sufficiente specificare .

IDG

La directory deliverable creata da PyInstaller. A causa del gran numero di file nella directory, un progetto di installazione di terze parti come NSIS può essere utilizzato per imballare la directory in un archivio autoestraente e creare automaticamente un collegamento all’eseguibile.,

Un’esclusione comune che puoi fare ètkinter, la libreria Python per la creazione di semplici interfacce utente grafiche multipiattaforma. Per impostazione predefinita, tkinter e tutti i suoi file di supporto sono imballati con un progetto PyInstaller. Se non stai usando tkinternel tuo progetto, puoi escluderlo aggiungendo 'tkinter'all’elenco excludes. Omettendo tkinter si ridurrà la dimensione del pacchetto di circa 7 MB.

Un’altra esclusione comune sono le suite di test., Se un pacchetto importato dal programma ha una suite di test, la suite di test potrebbe finire per essere inclusa nel pacchetto PyInstaller. A meno che non si esegua effettivamente la suite di test nel programma distribuito, è possibile escluderla in modo sicuro.

Tieni presente che i pacchetti creati usando le esclusioni devono essere accuratamente testati prima di essere usati. Se si finisce per escludere la funzionalità utilizzata in uno scenario futuro che non si è previsto, l’app si interromperà.

Suggerimenti per PyInstaller

  • Crea il tuo pacchetto PyInstaller sul sistema operativo su cui intendi distribuire., PyInstaller non supporta build multipiattaforma. Se è necessario distribuire l’app Python autonoma su sistemi macOS, Linux e Windows, sarà necessario installare PyInstaller e creare versioni separate dell’app su ciascuno di questi sistemi operativi.
  • Costruisci il tuo pacchetto PyInstaller mentre sviluppi la tua app. Non appena saprai che distribuirai il tuo progetto con PyInstaller, crea il tuo file.spec e inizia a perfezionare il pacchetto PyInstaller in parallelo con lo sviluppo della tua app., In questo modo puoi aggiungere esclusioni o inclusioni mentre vai e testare il modo in cui le nuove funzionalità vengono distribuite con l’app mentre le scrivi.
  • Non utilizzare la modalità --onefile di PyInstaller. PyInstaller include un interruttore della riga di comando, --onefile, che racchiude l’intera app in un singolo eseguibile autoestraente. Questo suona come una grande idea-devi solo consegnare un file! – ma ha delle insidie. Ogni volta che si esegue l’applicazione, deve prima decomprimere tutti i file all’interno del file eseguibile in una directory temporanea., Se l’applicazione è grande (200 MB, per esempio), disimballaggio può significare un ritardo di alcuni secondi. Usa invece la modalità di directory singola predefinita e impacchetta tutto come file.zip.
  • Crea un programma di installazione per la tua app PyInstaller. Se vuoi un modo per distribuire la tua app diverso da a .file zip, considerare l’utilizzo di un programma di utilità di installazione come il sistema di installazione Scriptable open source Nullsoft. Aggiunge pochissimo sovraccarico alla dimensione del deliverable e consente di configurare molti aspetti del processo di installazione, come la creazione di collegamenti al tuo eseguibile.,
  • Non aspettarti accelerazioni. PyInstaller è un sistema di pacchettizzazione, non un compilatore o un ottimizzatore. Il codice confezionato con PyInstaller non viene eseguito più velocemente di quanto farebbe quando viene eseguito sul sistema originale. Se si desidera accelerare il codice Python, utilizzare una libreria con accelerazione C adatta all’attività o un progetto come Cython.,w per accelerare Python
  • Come installare Python in modo intelligente
  • Meglio di Python per la gestione del progetto con la Poesia
  • Virtualenv e venv: Python ambienti virtuali spiegato
  • Python virtualenv e venv fare e cosa non fare
  • Python filettatura e procedimenti spiegati
  • Come usare il Python debugger
  • Come utilizzare timeit al profilo di codice Python
  • Come utilizzare cProfile al profilo di codice Python
  • iniziare con async in Python
  • Come utilizzare asyncio in Python
  • Come per la conversione Python JavaScript (e di nuovo)