back to top

I package in Python

I moduli possono essere considerati sia dei contenitori (di definizioni, istruzioni, metodi..) che dei contenuti collezionabili all’interno di insiemi più strutturati detti package. Questi ultimi rispondono alla necessità di organizzare i moduli in modo razionale: plausibilmente uno sviluppatore lavorerà in modo più semplice e produttivo se potrà dedicare spazi differenti a moduli con funzionalità diverse, per questo motivo i package consentono di catalogare i moduli e di suddividerli in base allo scopo per cui sono stati realizzati.

Struttura dei package

Come anticipato i package sono degli insiemi di moduli, funzionano in pratica come delle directory. Quando per esempio vogliamo organizzare al meglio la nostra posta elettronica facciamo ricorso a delle cartelle, dedicandone una alle email di lavoro, un’altra alla corrispondenza personale, un’altra ancora allo spam e così via; se poi abbiamo la necessità di gestire i messaggi in modo ancora più articolato, possiamo creare delle sotto-cartelle, per esempio dividendo le email di lavoro sulla base dei clienti o dei progetti che si stanno sviluppando. Nello stesso modo i package possono contenere a loro volta dei sub-package con i quali specializzare ulteriormente la divisione dei moduli.

Perché una directory venga riconosciuta da Python come packageè previsto in alcuni casi che essa contenga un file denominato in questo modo: __init__.py, non è obbligatorio che in esso vi sia del contenuto e la sua importanza è andata via via diminuendo con le più recenti versioni di Python (venne introdotto nella release 2.x), ma può essere utilizzato per ospitare il codice per l’inizializzazione di un modulo. In ogni caso in Python 3.3 sono stati implementati i cosiddetti "Implicit Namespace Packages" che, di fatto, permettono di creare anche package privi di "__init__.py".

Importazione dei moduli dai package

Per analizzare un esempio pratico sul funzionamento dei package creaiamo innanzitutto un directory chiamata "Progetti" sullo stesso percorso del nostro modulo "xmenoy", quindi copiamo il file di ques’ultimo all’interno di "Progetti" rinominandolo in "project_app_xmenoy.py". Per completezza, sempre in "Progetti" creiamo un file vuoto salvandolo come "__init__.py".

Per richiamare il modulo "project_app_xmenoy" non dovremo fare altro che concatenarne il nome a quello del package in fase di importazione:

# Importare un modulo da un package
>>> import Progetti.project_app_xmenoy
10
8

Il nome di un package può essere espresso o iniziare sia con caratteri maiuscoli che minuscoli, ma per convenzione si utilizza l’iniziale maiuscola in modo da distinguere più facilmente i package dai moduli. Stesso discorso per quanto riguarda i sub-package, quindi se "project_app_xmenoy" si dovesse trovare nella sub-directory "Guide" della directory "Progetti", l’istruzione necessaria per la sua importazione dovrà essere la seguente:

# Importare un modulo da un sub-package
>>> import Progetti.Guide.project_app_xmenoy
10
8

Importare funzioni dai moduli dei package

Il modulo "project_app_xmenoy" prevede di restituire immediatamente un valore di ritorno frutto di una sottrazione, ma come dovremmo procedere se volessimo richiamare una singola funzione di un modulo che richiede il passaggio di parametri?

Per rispondere a questa domanda recuperiamo il modulo "app" e ricordiamo che esso contiene una funzione, "mul()", con cui eseguire la moltiplicazione di due valori numerici da utilizzare come fattori. Copiamo quindi il file "app.py" nel sub-package "Guide" del package "Progetti" e rinominiamolo in "project_app_mul.py"; fatto questo potremo richiamare direttamente la funzione desiderata in questo modo:

# Chiamata della funzione di un sub-package
>>> import Progetti.Guide.project_app_mul
>>> Progetti.Guide.project_app_mul.mul(7,8)
56

La sintassi prevista è quindi estremamente semplice, si ricordi però che i package vanno concatenati rispettando il loro ordine gerarchico (package tree), per cui il package principale dovrà essere indicato sempre per primo, seguito da un suo sub-package, da un eventuale sub-package di quest’ultimo e così via. Il nome del modulo richiesto andrà indicato dopo quelli dei package e potrà precedere unicamente il nome di una funzione, di una variabile o di una classe.

Nel caso in cui si voglia importare soltanto una determinata funzione di un modulo lo si potrà fare tramite il costrutto "from .. import", in questo modo:

# Importazione di una funzione da un sub-package
>>> from Progetti.Guide.project_app_mul import mul

Questa istruzione consentirà di utilizzare direttamente la funzione desiderata:

# Uso diretto di una funzione importata da un sub-package
>>> from Progetti.Guide.project_app_mul import mul
>>> mul(9,8)
72

Si consiglia in ogni caso di utilizzare quest’ultimo metodo con una certa cautela, omettere la gerarchia dei package potrebbe infatti generare confusione e rendere il codice meno leggibile.

Pubblicità
Claudio Garau
Claudio Garau
Web developer, programmatore, Database Administrator, Linux Admin, docente e copywriter specializzato in contenuti sulle tecnologie orientate a Web, mobile, Cybersecurity e Digital Marketing per sviluppatori, PA e imprese.