I moduli, anche conosciuti come librerie in altri linguaggi, sono dei file usati per raggruppare costanti, funzioni e classi, che ci consentono di suddividere e organizzare meglio i nostri progetti. Python include già una lista estensiva di moduli standard (anche conosciuti come standard library), ma è anche possibile scaricarne o definirne di nuovi.
Importare moduli
Prima di poter accedere ai contenuti di un modulo, è necessario importarlo. Per farlo, usiamo il costrutto import
:
>>> import math # importiamo il modulo math della libreria standard
>>> math # l'import crea una nuova variabile che si riferisce al modulo
<module 'math' (built-in)>
>>> help(math) # possiamo usare help() per vedere la documentazione del modulo
Help on built-in module math:
NAME
math
DESCRIPTION
This module is always available. It provides access to the
mathematical functions defined by the C standard.
FUNCTIONS
...
DATA
e = 2.718281828459045
inf = inf
nan = nan
pi = 3.141592653589793
FILE
(built-in)
>>> dir(math) # possiamo usare dir() per vedere il contenuto del modulo
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin',
'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e',
'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum',
'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp',
'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians',
'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
>>>
>>> math.pi # math.pi è una costante che corrisponde al valore di pi greco
3.141592653589793
>>> math.sqrt # math.sqrt è una funzione in grado di calcolare la radice quadrata
<built-in function sqrt>
>>> help(math.sqrt) # possiamo usare help() per vedere la documentazione della funzione
Help on built-in function sqrt in module math:
sqrt(...)
sqrt(x)
Return the square root of x.
>>> math.sqrt(64) # possiamo chiamarla per calcolare la radice quadrata di 64
8.0
Come si vede nell'esempio, la forma più semplice del costrutto import
e import nome_modulo
. In questo caso abbiamo importato il modulo della standard library chiamato math
, che include diverse costanti e funzioni matematiche. Dopo l'esecuzione dell'import
, Python ha definito una nuova variabile chiamata math
che si riferisce al modulo math
. Possiamo quindi usare le funzioni dir()
e help()
per esplorare i contenuti del modulo, e ottenere quindi una lista di nomi definiti nel modulo e la loro documentazione. Per accedere a questi nomi, possiamo usare la sintassi modulo.nome
: ad esempio math.pi
è una costante che rappresenta il valore di pi greco, mentre math.sqrt
è una funzione che può essere usata per calcolare la radice quadrata (square root) di un numero.
Questa forma di import
ci consente di accedere a qualsiasi nome definito all'interno del modulo, ma per farlo dobbiamo sempre usare la sintassi modulo.nome
. È anche possibile importare nomi direttamente usando la sintassi from modulo import nome
:
>>> from math import pi, sqrt # importa solo i nomi pi e sqrt dal modulo math
>>> pi # è ora possibile accedere a pi senza usare math.pi
3.141592653589793
>>> sqrt # è ora possibile accedere a sqrt senza usare math.sqrt
<built-in function sqrt>
Questa forma di import
ci permette di importare uno o più nomi direttamente, evitandoci quindi di ripetere il nome del modulo ogni volta. Tuttavia, ciò non ci consente di accedere agli altri nomi del modulo e può risultare ambigua se il nome della funzione non è abbastanza chiaro. Quest'ultimo problema può essere risolto usando i costrutti import modulo as nuovonome
e from modulo import nome as nuovonome
:
>>> import math as matematica # importa il modulo math chiamandolo matematica
>>> matematica.pi # possiamo accedere agli oggetti di math facendo matematica.nome
3.141592653589793
>>>
>>> from math import sqrt as radice_quadrata # importa sqrt chiamandolo radice_quadrata
>>> radice_quadrata # radice_quadrata si riferisce lo stesso a sqrt
<built-in function sqrt>
>>> radice_quadrata(64) # e funziona come sqrt originale, ma ha un nome diverso
8.0
Questa tecnica può essere usata anche nel caso in cui i nomi siano particolarmente lunghi o per evitare conflitti tra nomi simili o uguali che appartengono a moduli diversi.
Esiste infine un'altra forma che ci permette di importare tutti i nomi di un modulo, usando la sintassi from modulo import *
:
>>> from math import * # importa tutti i nomi definiti nel modulo math
>>> pi # possiamo ora accedere direttamente a tutti i nomi di math
3.141592653589793
>>> e # dalle costanti
2.718281828459045
>>> sqrt # alle funzioni
<built-in function sqrt>
>>> sin
<built-in function sin>
>>> cos
<built-in function cos>
>>> tan
<built-in function tan>
Anche se possibile, questa forma di import
è generalmente sconsigliata.
Per riassumere:
import modulo
va bene quando abbiamo bisogno di accedere a diversi nomi di un modulo senza doverli importare individualmente e a quando vogliamo sapere esplicitamente a che modulo appartiene ogni funzione che chiamiamo (ad esempiomath.pi
ci dice esplicitamente che stiamo accedendo alla costante matematica pi);from modulo import nome
va bene quando abbiamo bisogno di accedere a un numero limitato di nomi, e quando questi nomi sono abbastanza chiari da evitare ambiguità (ad esempio una funzionesearch
potrebbe cercare diverse cose a seconda del modulo, mentre la funzionesqrt
serve chiaramente a calcolare la radice quadrata);import modulo as nuovonome
efrom modulo import nome as nuovonome
va bene quando i nomi che vogliamo importare sono ambigui o particolarmente lunghi;from modulo import *
può andare bene dall'interprete interattivo (se ad esempio vogliamo usarlo come una potente calcolatrice facendofrom math import *
) o quando conosciamo esattamente il contenuto del modulo, abbiamo bisogno di tutti i nomi, e siamo sicuri che questi nomi non creano conflitti con nomi esistenti (se ad esempio un modulo contiene una funzione chiamataopen
, l'esecuzione difrom modulo import *
andrà a sovrascrivere la funzione builtinopen
).
Quando importiamo un modulo, Python deve trovare il file corrispondente, e per farlo controlla in ordine le directory elencate nella lista sys.path
. Una volta trovato il file, Python lo importa, crea un module object (oggetto modulo), e lo salva nel dizionario sys.modules
. Se il modulo viene importato nuovamente in un altro punto del programma, Python è in grado di recuperare il modulo da sys.modules
senza doverlo importare nuovamente. Inoltre, i moduli .py
vengono compilati in bytecode: un formato più efficiente che viene salvato in file con estensione .pyc
che a loro volta vengono salvati in una cartella chiamata __pycache__
. Quando viene eseguito un programma che ha bisogno di importare un modulo, se modulo.pyc
esiste già ed è aggiornato, allora Python importerà quello invece di ricompilare il modulo in bytecode ogni volta.
La libreria standard e PyPI
Oltre al modulo math
che abbiamo visto nei precedenti esempi, Python include già dozzine di moduli che coprono la maggior parte delle operazioni più comuni. Tutti questi moduli sono già presenti in Python e possono essere importati direttamente senza dover scaricare nulla. Alcuni tra i moduli più comunemente usati, divisi per aree, sono:
- elaborazione di testo:
re
(che fornisce supporto per le espressioni regolari) - tipi di dato:
datetime
(per rappresentare date e ore),collections
(diversi tipi di oggetti contenitori),enum
(per enumerazioni) - moduli numerici e matematici:
math
(funzioni matematiche),decimal
(supporto per aritmetica a virgola mobile),random
(generazione di numeri pseudo-casuali),statistics
(funzioni statistiche) - programmazione funzionale:
itertools
(funzioni per lavorare con gli iteratori),functools
(funzioni di ordine superiore) - accesso a file e directory:
pathlib
(oggetti per la rappresentazione e manipolazione di file e directory),shutil
(operazioni di alto livello sui file) - persistenza di dati:
sqlite3
(interfaccia a database SQLite) - compressione e archiviazione di dati:
zipfile
(supporto per archivi ZIP),tarfile
(supporto per archivi tar),gzip
(supporto per file gzip) - formati di file:
csv
(supporto per file CSV),configparser
(supporto per file CFG/INI) - servizi generici del sistema operativo:
os
(diverse interfacce del sistema operativo),io
(strumenti per lavorare con file e stream),time
(funzioni relative al tempo),argparse
(per passare argomenti ricevuti dalla linea di comando),logging
(funzioni e classi per il logging) - esecuzione concorrente:
subprocess
(gestione di sotto-processi),multiprocessing
(parallelismo basato su processi),threading
(parallismo basato su thread) - comunicazione tra processi e networking:
asyncio
(I/O asincrono),socket
(interfaccia di rete di basso livello),ssl
(wrapper TLS/SSL per i socket) - gestione di formati di internet:
json
(supporto per file JSON),email
(supporto per email) - elaborazione di formati di markup: il package
html
(strumenti per lavorare con HTML), il packagexml
(strumenti per lavorare con xml) - protocolli internet: il package
urllib
(gestione di URL),httplib
(strumenti per lavorare con il protocollo HTTP),ftplib
(strumenti per lavorare con FTP) - internazionalizzazione:
gettext
(strumenti per supportare linguaggi multipli) - interfacce grafiche: il package
tkinter
(interfaccia con Tcl/Tk) - tool per lo sviluppo:
unittest
(strumenti per testare il codice) - debugging e profiling:
pdb
(debugger per Python),timeit
(strumenti per misurare il tempo di esecuzione di brevi pezzi di codice),cProfile
(profiler per identificare le parti più lente di un programma) - servizi di runtime:
sys
(funzioni e parametri di sistema),contextlib
(strumenti per lavorare con i context manager)
Nella documentazione ufficiale possiamo trovare l'elenco completo dei moduli della libreria standard di Python.
Se invece necessitiamo di moduli che non sono inclusi nella libreria standard, possiamo consultare PyPI: il Python Package Index. PyPI è un repository che include decine di migliaia di moduli che possono essere scaricati e installati in modo molto semplice usando un tool chiamato pip, che approfondiremo in una apposita lezione successiva.