importlib - Il Meccanismo di Importazione di Python
Scopo: Espone l'implementazione dell'istruzione import di Python
Il modulo importlib include funzioni che implementano il meccanismo di importazione di Python per il caricamento di codice in moduli e pacchetti. Costituisce un punto di accesso per importare dinamicamente i moduli, utile in taluni casi dove il nome del modulo che deve essere importato non è noto quando il codice viene scritto (ad esempio per
Pacchetto di esempio
Gli esempi di questo articolo usano un pacchetto chiamato esempio
con __init__.py
.
# esempio/__init__.py
print('Importazione pacchetto di esempio')
Il pacchetto contiene anche submodule.py
.
# esempio/submodule.py
print('Importazione di submodule')
Prestare attenzione al testo stampato dalle chiamate a print()
quando il pacchetto o il modulo viene importato.
Tipi di Modulo
Python supporta parecchi stili di moduli, ognuno dei quali richiede il suo proprio modo di gestione quando viene aperto e aggiunto allo spazio dei nomi, e il supporto per i formati varia a seconda della piattaforma. Ad esempio, sotto Microsoft Windows, le librerie condivise sono caricate da file con estensioni .dll
o .pyd
, invece che .so
. Anche le estensioni per i moduli C potrebbero cambiare quando si usa una compilazione per debug dell'interprete invece che una normale compilazione di rilascio, visto che possono anche essere compilati con informazioni di debug incluse. Se una estensione di libreria C o altro modulo non viene caricato nel modo atteso, si utilizzino le costanti definite in importlib.machinery
per trovare i tipi supportati dalla piattaforma corrente, e i parametri per caricarle.
# importlib_suffixes.py
import importlib.machinery
SUFFIXES = [
('Sorgente:', importlib.machinery.SOURCE_SUFFIXES),
('Debug:',
importlib.machinery.DEBUG_BYTECODE_SUFFIXES),
('Ottimizzato:',
importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES),
('Bytecode:', importlib.machinery.BYTECODE_SUFFIXES),
('Estensione:', importlib.machinery.EXTENSION_SUFFIXES),
]
def main():
tmpl = '{:<12} {}'
for name, value in SUFFIXES:
print(tmpl.format(name, value))
if __name__ == '__main__':
main()
Il valore ritornato è una sequenza di tuple che contengono l'estensione del file, la modalità usata per aprire il file contenente il modulo e un tipo codice da una costante definita nel modulo. Questa tabella è incompleta visto che alcuni dei tipi importabili di modulo o pacchetto non corrispondono a singoli file.
$ python3 importlib_suffixes.py Sorgente: ['.py'] Debug: ['.pyc'] Ottimizzato: ['.pyc'] Bytecode: ['.pyc'] Estensione: ['.cpython-38-x86_64-linux-gnu.so', '.abi3.so', '.so']
Importare Moduli
L'API di alto livello in importlib rende semplice importare un modulo dato un nome assoluto o relativo. Quando si usa un nome di modulo relativo, si specifichi il pacchetto che contiene il modulo come argomento separato.
# importlib_import_module.py
import importlib
m1 = importlib.import_module('esempio.submodule')
print(m1)
m2 = importlib.import_module('.submodule', package='esempio')
print(m2)
print(m1 is m2)
Il valore ritornato da import_module()
è l'oggetto del modulo che era stato creato dall'importazione.
$ python3 importlib_import_module.py Importazione pacchetto di esempio Importazione di submodule <module 'esempio.submodule' from '.../esempio/submodule.py'> <module 'esempio.submodule' from '.../esempio/submodule.py'> True
Se il modulo non può essere importato, import_module()
solleva una eccezione ImportError
.
# importlib_import_module_error.py
import importlib
try:
importlib.import_module('esempio.nosuchmodule')
except ImportError as err:
print('Errore:', err)
Il messaggio di errore include il nome del modulo mancante.
$ python3 importlib_import_module_error.py Importazione pacchetto di esempio Errore: No module named 'esempio.nosuchmodule'
Per ricaricare un modulo esistente, si usi reload()
.
# importlib_reload.py
import importlib
m1 = importlib.import_module('esempio.submodule')
print(m1)
m2 = importlib.reload(m1)
print(m1 is m2)
Il valore di ritorno da reload()
è il nuovo modulo. A seconda del tipo di caricatore usato, potrebbe essere la stessa istanza del modulo.
$ python3 importlib_reload.py Importazione pacchetto di esempio Importazione di submodule <module 'esempio.submodule' from '.../esempio/submodule.py'> Importazione di submodule True
Caricatori
L'API di alto livello in importlib fornisce l'accesso agli oggetti di caricamento, Per ottenere un caricatore per un modulo si usi find_loader()
. Poi per recuperare il modulo si usi il metodo load_module()
.
# importlib_find_loader.py
import importlib
loader = importlib.find_loader('esempio')
print('Caricatore:', loader)
m = loader.load_module()
print('Modulo:', m)
Questo esempio carica il livello superiore del pacchetto esempio
.
$ python3 importlib_find_loader.py Caricatore: <_frozen_importlib_external.SourceFileLoader object at 0x7fe2aac50fd0> Importazione pacchetto di esempio Modulo: <module 'esempio' from '.../esempio/__init__.py'>
I sottomoduli all'interno dei pacchetti devono essere caricati separatamente usando il percorso dal pacchetto. Nell'esempio seguente, il pacchetto prima viene caricato, quindi il suo percorso viene passato a find_loader()
per creare un caricatore in grado di caricare il sottomodulo.
# importlib_submodule.py
import importlib
pkg_loader = importlib.find_loader('esempio')
pkg = pkg_loader.load_module()
loader = importlib.find_loader('submodule', pkg.__path__)
print('Caricatore:', loader)
m = loader.load_module()
print('Modulo:', m)
Diversamente da import_module()
, il nome del sottomodulo dovrebbe essere passato senza alcun prefisso di percorso relativo, visto che il caricatore sarà già limitato dal percorso del pacchetto.
$ python3 importlib_submodule.py Importazione pacchetto di esempio Caricatore: <_frozen_importlib_external.SourceFileLoader object at 0x7f893b8de1d0> Importazione di submodule Modulo: <module 'submodule' from '.../esempio/submodule.py'>
Vedere anche:
- importlib
- La documentazione della libreria standard per questo modulo.
- Moduli e importazioni
- Agganci per importazione, il percorso di ricerca del modulo e altri meccanismi correlati nel modulo sys (in corso di traduzione)
- inspect
- Carica programmaticamente informazioni da un modulo.
- PEP 302
- Nuovi agganci per l'importazione
- PEP 369
- Agganci dopo l'importazione
- PEP 488
- Eliminazione dei file PYO