8.6. Importare dinamicamente i moduli

Ok, abbiamo filosofeggiato abbastanza. Vediamo come si importano dinamicamente i moduli.

Per cominciare osservate come vengono importati normalmente i moduli. La sintassi import module rimanda al percorso di ricerca per trovare un modulo e lo importa per nome. Si possono anche importare più moduli contemporaneamente usando una lista separata da virgole, è stato fatto nella prima riga di codice di questo capitolo.

Esempio 8.13. Importare contemporaneamente più moduli


import sys, os, re, unittest 1
1 Questa riga importa quattro moduli in una istruzione: sys (per funzioni di sistema ed accesso ai parametri della riga di comando), os (per operazioni legate al sistema operativo, come ad esempio elencare directory), re (per le espressioni regolari) e unittest (per i test delle unità di codice).

Adesso facciamo la stessa cosa, però con l'importazione dinamica.

Esempio 8.14. Importare moduli dinamicamente

>>> sys = __import__('sys')           1
>>> os = __import__('os')
>>> re = __import__('re')
>>> unittest = __import__('unittest')
>>> sys                               2
>>> <module 'sys' (built-in)>
>>> os
>>> <module 'os' from '/usr/local/lib/python2.2/os.pyc'>
1 La funzione built-in __import__ ha lo stesso obiettivo dell'istruzione import, però è una vera funzione ed accetta una stringa come argomento.
2 La variabile sys adesso è il modulo sys, come se avessimo fatto import sys. La variabile os adesso è il modulo os, e così via.

Quindi __import__ importa moduli, però con una stringa come argomento. In questo caso il modulo che abbiamo importato era un parametro statico, ma poteva essere una variabile o anche il risultato di una chiamata a funzione. Inoltre la variabile a cui assegnamo il modulo può avere un nome qualsiasi o anche essere un elemento di una lista.

Esempio 8.15. Importare dinamicamente una lista di moduli

>>> moduleNames = ['sys', 'os', 're', 'unittest'] 1
>>> moduleNames
['sys', 'os', 're', 'unittest']
>>> modules = map(__import__, moduleNames)        2
>>> modules                                       3
[<module 'sys' (built-in)>,
<module 'os' from 'c:\Python22\lib\os.pyc'>,
<module 're' from 'c:\Python22\lib\re.pyc'>,
<module 'unittest' from 'c:\Python22\lib\unittest.pyc'>]
>>> modules[0].version                            4
'2.2.2 (#37, Nov 26 2002, 10:24:37) [MSC 32 bit (Intel)]'
>>> import sys
>>> sys.version
'2.2.2 (#37, Nov 26 2002, 10:24:37) [MSC 32 bit (Intel)]'
1 moduleNames è una semplice lista di stinghe. Niente di strano, eccetto che le stringhe potrebbero essere nomi di moduli che, nel caso serva, possiamo importare.
2 Sorpresa, volevamo importarli, e lo abbiamo fatto mappando la funzione __import__ sulla lista. Ricordate, map prende ogni elemento della lista (moduleNames) e chiama la funzione (__import__) una volta per ogni elemento della lista, compone una lista con i risultati e la restituisce.
3 Adesso da una lista di stringhe abbiamo creato una lista di veri e propri moduli. (Gli indirizzi potrebbero essere diversi, dipendono dal sistema operativo dove è installato Python, dalle fasi della luna, etc.)
4 Per aver conferma che sono moduli veri, andiamo a vedere alcuni attributi. Ricodate, modules[0] è il modulo sys ed infatti modules[0].version è identico a sys.version. Ovviamente sono disponibili anche tutti gli attributi ed i metodi degli altri moduli della lista. Ma non c'è niente di magico né nell'istruzione import, né nei moduli. Infatti anche i moduli sono oggetti. Tutto è un oggetto.

Ora dovremmo essere in grado di comprendere il significato della maggior parte degli esempi di questo capitolo.