imp - Interfaccia al meccanismo di importazione modulo.

Scopo Espone l'implementazione dell'istruzione Python import.
Versione Python 2.2.1 e superiore

Il modulo imp comprende funzioni che espongono parte dell'implementazione sottostante il meccanismo di importazione di Python per caricare il codice in pacchetti e moduli. E' un punto di accesso per l'importazione dinamica di moduli, ed è utile in alcuni casi laddove non si conosce il nome del modulo che occorre importare quando si sta scrivendo il proprio codice (es. per plugin od estensioni di una applicazione).

Il Pacchetto Example

Gli esempi seguenti usano un pacchetto chiamato "example" con __init__py:

print 'Importazione del pacchetto example'

ed un modulo chiamato submodule che contiene:

print 'Importazione di submodule'

Si osservi il testo stampato dalle istruzioni print nell'output di esempio quando il pacchetto od il modulo sono importati.

Tipi di modulo

Python supporta parecchi stili di moduli. Ognuno dei quali richiede la sua propria gestione in fase di apertura ed aggiunta allo spazio dei nomi. Alcuni dei tipi supportati ed i loro parametri possono essere elencati dalla funzione get_suffixes().

import imp

module_types = { imp.PY_SOURCE:   'sorgente',
                 imp.PY_COMPILED: 'compilato',
                 imp.C_EXTENSION: 'estensione',
                 imp.PY_RESOURCE: 'risorsa',
                 imp.PKG_DIRECTORY: 'pacchetto',
                 }

def main():
    fmt = '%10s %10s %10s'
    print fmt % ('Estensione', 'Modalità', 'Tipo')
    print '-' * 32
    for extension, mode, module_type in imp.get_suffixes():
        print fmt % (extension, mode, module_types[module_type])

if __name__ == '__main__':
    main()

get_suffixes() restituisce una sequenza di tuple che contiene l'estensione del file, la modalità usata per aprire il file, ed un tipo codice ottenuto da una costante definita nel modulo. Questa tabella è incompleta, poichè alcuni dei moduli o tipi di pacchetto importabili non corrispondono a singoli file.

$ python imp_get_suffixes.py

Estensione  Modalità       Tipo
--------------------------------
       .so         rb estensione
 module.so         rb estensione
       .py          U   sorgente
      .pyc         rb  compilato

Trovare Moduli

Il primo passo per caricare un modulo è trovarlo. find_module() scorre il percorso di ricerca di importazione cercando un pacchetto o modulo con il nome fornito. Restituisce un handle di file aperto (se appropriato per il tipo), filename (il nome del file) dove il modulo è stato trovato, e description (una tupla tipo quella restituita da get_suffixes()).

import imp
from imp_get_suffixes import module_types

print 'Pacchetto:'
f, filename, description = imp.find_module('example')
print module_types[description[2]], filename
print

print 'Sub-modulo:'
f, filename, description = imp.find_module('submodule', [filename])
print module_types[description[2]], filename
if f: f.close()
$ python imp_find_module.py

Pacchetto:
pacchetto /home/robby/pydev/pymotw-it/dumpscripts/example

Sub-modulo:
sorgente /home/robby/pydev/pymotw-it/dumpscripts/example/submodule.py

Se find_module non riesce a trovare il modulo, solleva una eccezione ImportError.

import imp

try:
    imp.find_module('modulo_che_non_esiste')
except ImportError, err:
    print 'ImportError:', err
$ python imp_find_module_error.py

ImportError: No module named modulo_che_non_esiste

Caricare Moduli

Una volta che si è trovato il modulo si usa load_module() per importarlo effettivamente. load_module() riceve il percorso completo del modulo (punti inclusi) ed i valori restituiti da find_module() (la tupla con l'handle di file aperto, il nome del file e la descrizione).

import imp

f, filename, description = imp.find_module('example')
example_package = imp.load_module('example', f, filename, description)
print 'Pacchetto:', example_package

f, filename, description = imp.find_module('submodule',
                                           example_package.__path__)
try:
    submodule = imp.load_module('example.module', f, filename, description)
    print 'Sub-modulo:', submodule
finally:
    f.close()

load_module() crea un nuovo oggetto modulo con il nome fornito, carica il codice contenuto, quindi lo aggiunge a sys.modules

$ python imp_load_module.py

Importazione del pacchetto example
Pacchetto: 
Importazione di submodule
Sub-modulo: 

Chiamando load_module() per un modulo che è già stato importato, si ottiene lo stesso effetto della chiamata di reload() sull'oggetto modulo esistente

import imp
import sys

for i in range(2):
    print i,
    try:
        m = sys.modules['example']
    except KeyError:
        print '(non in sys.modules)',
    else:
        print '(presente in sys.modules)',
    f, filename, description = imp.find_module('example')
    example_package = imp.load_module('example', f, filename, description)

Invece di creare un nuovo modulo, il contenuto del modulo esistente viene semplicemente rimpiazzato.

$ python imp_load_module_reload.py

0 (non in sys.modules) Importazione del pacchetto example
1 (presente in sys.modules) Importazione del pacchetto example

Vedere anche:

imp
La documentazione della libreria standard per questo modulo
Moduli ed Import
Agganci per importazione, il percorso di ricerca dei moduli ed altro.
inspect
Carica informazioni per un modulo programmaticamente.
PEP 302
Nuovi agganci per import
POP 369
Agganci post import.