Subsections


6. Moduli

Se si esce dall'interprete Python e poi vi si rientra, le definizioni introdotte (funzioni e variabili) vengono perse. Perciò, se si desidera scrivere un programma un po' più lungo, è meglio usare un editor di testo per preparare un file da usare come input al lancio dell'interprete. Ciò viene chiamato creazione di uno script. Con l'aumentare delle dimensioni del proprio programma, si potrebbe volerlo suddividere in più file per facilitarne la manutenzione. Si potrebbe anche voler riutilizzare in programmi diversi una funzione utile che si è già scritta senza doverne copiare l'intera definizione in ogni programma.

A tale scopo, Python permette di porre le definizioni in un file e usarle in uno script o in una sessione interattiva dell'interprete. Un file di questo tipo si chiama modulo; le definizioni presenti in un modulo possono essere importate in altri moduli o entro il modulo main (la collezione di variabili cui si ha accesso in uno script eseguito al livello più alto e in modalità calcolatrice).

Un modulo è un file che contiene definizioni e istruzioni Python. Il nome del file è il nome del modulo con il suffisso .py aggiunto. All'interno di un modulo, il nome del modulo è disponibile (sotto forma di stringa) come valore della variabile globale __name__. Per esempio, si usi il proprio editor di testo favorito per creare un file chiamato fibo.py nella directory corrente che contenga quanto segue:

# modulo dei numeri di Fibonacci

def fib(n):    # scrive le serie di Fibonacci fino a n
    a, b = 0, 1
    while b < n:
        print b,
        a, b = b, a+b

def fib2(n): # restituisce le serie di Fibonacci fino a n
    result = []
    a, b = 0, 1
    while b < n:
        result.append(b)
        a, b = b, a+b
    return result

Ora si lanci l'interprete Python e si importi questo modulo con il seguente comando:

>>> import fibo

Ciò non introduce i nomi delle funzioni definite in fibo direttamente nella tabella dei simboli corrente; vi introduce solo il nome del modulo fibo. Usando il nome del modulo è possibile accedere alle funzioni:

>>> fibo.fib(1000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'

Se si intende usare spesso una funzione, si può assegnare ad essa un nome locale:

>>> fib = fibo.fib
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377


6.1 Di più sui moduli

Un modulo può contenere istruzioni eseguibili oltre che definizioni di funzione. Queste istruzioni servono ad inizializzare il modulo. Esse sono eseguite solo la prima volta che il modulo viene importato da qualche parte.6.1

Ogni modulo ha la sua tabella dei simboli privata, che è usata come tabella dei simboli globale da tutte le funzioni definite nel modulo. Quindi l'autore di un modulo può utilizzare le variabili globali nel modulo senza preoccuparsi di conflitti accidentali con le variabili globali di un utente. D'altro canto, se si sa quel che si sta facendo, si può accedere alle variabili globali di un modulo mediante la stessa notazione usata per riferirsi alle sue funzioni, nome_modulo.nome_elemento.

I moduli possono importare altri moduli. È uso comune, ma non indispensabile, mettere tutte le istruzioni import all'inizio del modulo (o dello script, in questo ambito). I nomi dei moduli importati vengono inseriti nella tabella dei simboli globali del modulo che li importa.

C'è una variante dell'istruzione import che importa nomi da un modulo direttamente nella tabella dei simboli del modulo che li importa. Per esempio:

>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

In questo modo non si introduce il nome del modulo dal quale vengono importati i nomi nella tabella dei simboli locali (così nell'esempio sopra fibo non è definito).

C'è anche una variante per importare tutti i nomi definiti in un modulo:

>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

In questo modo si importano tutti i nomi tranne quelli che iniziano con un `underscore' (_).


6.1.1 Il percorso di ricerca del modulo

Quando un modulo di nome spam viene importato, l'interprete cerca un file chiamato spam.py nella directory corrente, e quindi nella lista di directory specificata dalla variabile d'ambiente PYTHONPATH. Tale variabile ha la stessa sintassi della variabile di shell PATH, cioè una lista di nomi di directory. Quando PYTHONPATH non è configurata, o quando il file non si trova nelle directory ivi menzionate, la ricerca continua su un percorso predefinito dipendente dall'installazione; su Unix di solito si tratta di .:/usr/local/lib/python.

In effetti i moduli vengono cercati nella lista delle directory contenuta nella variabile sys.path, che è inizializzata con la directory che contiene lo script in input (o la directory corrente), la PYTHONPATH e il valore predefinito dipendente dall'installazione. Questo permette ai programmi Python scritti con cognizione di causa di modificare o rimpiazzare il percorso di ricerca dei moduli. Si noti che, siccome la directory corrente contiene lo script che deve essere eseguito, è importante che non abbia lo stesso nome di un modulo standard, altrimenti Python cercherà di importare lo script come se fosse un modulo. Questo genererà un errore. Si veda la sezione 6.2, ``Moduli Standard'' più avanti.

6.1.2 File Python ``compilati''

Un'accelerazione rilevante dei tempi di avvio di brevi programmi che usano un sacco di moduli standard si ottiene se nella directory dove si trova spam.py esiste un file spam.pyc, ove si assume che questo contenga una versione già ``compilata'' a livello di ``bytecode'' del modulo spam. L'orario di modifica della versione di spam.py usata per creare spam.pyc viene registrata in spam.pyc, ed il file .pyc viene ignorato se gli orari non corrispondono.

Normalmente, non c'è bisogno di fare nulla per creare il file spam.pyc. Ogni volta che spam.py è stato compilato con successo, viene fatto un tentativo di scrivere su spam.pyc la versione compilata. Il fallimento di tale tentativo non comporta un errore; se per qualsiasi ragione non viene scritto completamente, il file spam.pyc risultante verrà riconosciuto come non valido e perciò successivamente ignorato. I contenuti di spam.pyc sono indipendenti dalla piattaforma, quindi una directory di moduli Python può essere condivisa da macchine con architetture differenti.

Alcuni consigli per esperti:


6.2 Moduli standard

Python viene fornito con una libreria di moduli standard, descritta in un documento separato, la Libreria di riferimento di Python (da qui in avanti verrà indicato come ``Libreria di riferimento''). Alcuni moduli sono interni all'interprete (``built-in''). Forniscono supporto a operazioni che non fanno parte del nucleo del linguaggio ma cionondimeno sono interne, per garantire efficienza o per fornire accesso alle primitive del sistema operativo, come chiamate di sistema. L'insieme di tali moduli è un'opzione di configurazione che dipende dalla piattaforma sottostante. Per esempio, il modulo amoeba è fornito solo su sistemi che in qualche modo supportano le primitive Amoeba. Un modulo particolare merita un po' di attenzione: sys, che è presente come modulo built-in in ogni interprete Python. Le variabili sys.ps1 e sys.ps2 definiscono le stringhe usate rispettivamente come prompt primario e secondario:

>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print 'Yuck!'
Yuck!
C>

Queste due variabili sono definite solo se l'interprete è in modalità interattiva.

La variabile sys.path è una lista di stringhe che determinano il percorso di ricerca dei moduli dell'interprete. Viene inizializzata con un percorso predefinito ottenuto dalla variabile di ambiente PYTHONPATH, o da un valore predefinito built-in se PYTHONPATH non è configurata. È possibile modificarla usando le operazioni standard delle liste, p.e.:

>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')


6.3 La funzione dir()

La funzione built-in dir() viene usata per ottenere i nomi definiti da un modulo. Essa restituisce una lista ordinata di stringhe:

>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__',
 '__stdin__', '__stdout__', '_getframe', 'api_version', 'argv', 
 'builtin_module_names', 'byteorder', 'callstats', 'copyright',
 'displayhook', 'exc_clear', 'exc_info', 'exc_type', 'excepthook',
 'exec_prefix', 'executable', 'exit', 'getdefaultencoding', 'getdlopenflags',
 'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode',
 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache',
 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags',
 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout',
 'version', 'version_info', 'warnoptions']

Invocata senza argomenti, dir() elenca i nomi attualmente definiti:

>>> a = [1, 2, 3, 4, 5]
>>> import fibo, sys
>>> fib = fibo.fib
>>> dir()
['__name__', 'a', 'fib', 'fibo', 'sys']

Si noti che la lista comprende tutti i tipi di nomi: variabili, moduli, funzioni, etc..

La funzione dir() non elenca i nomi delle funzioni e delle variabili built-in. Se se ne desidera l'elenco, si possono trovare le definizioni nel modulo __builtin__:

>>> import __builtin__
>>> dir(__builtin__)
['ArithmeticError', 'AssertionError', 'AttributeError',
 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
 'Exception', 'False', 'FloatingPointError', 'IOError', 'ImportError',
 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt',
 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
 'NotImplementedError', 'OSError', 'OverflowError', 'OverflowWarning',
 'PendingDeprecationWarning', 'ReferenceError',
 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration',
 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError',
 'True', 'TypeError', 'UnboundLocalError', 'UnicodeError', 'UserWarning',
 'ValueError', 'Warning', 'ZeroDivisionError', '__debug__', '__doc__',
 '__import__', '__name__', 'abs', 'apply', 'bool', 'buffer',
 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex',
 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod',
 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float',
 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id',
 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter',
 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'min',
 'object', 'oct', 'open', 'ord', 'pow', 'property', 'quit',
 'range', 'raw_input', 'reduce', 'reload', 'repr', 'round',
 'setattr', 'slice', 'staticmethod', 'str', 'string', 'sum', 'super',
 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']


6.4 I package

I ``package'' sono un modo di strutturare lo spazio dei nomi dei moduli di Python usando nomi di modulo separati da punti. Per esempio, il nome del modulo A.B designa un sottomodulo chiamato "B" in un package chiamato "A". Proprio come l'uso dei moduli permette ad autori di moduli differenti di non doversi preoccupare dei nomi delle rispettive variabili globali, usare nomi di moduli separati da punti risparmia agli autori di package multi-modulari come NumPy o PIL (Python Imaging Library) ogni preoccupazione circa i nomi dei moduli.

Si supponga di voler progettare una collezione di moduli (un ``package'') per il trattamento coerente di file e dati audio. Ci sono molti formati, diversi fra loro, per i file audio (di solito riconoscibili dalla loro estensione, p.e. .wav, .aiff, .au), quindi potrebbe essere necessario creare e mantenere una collezione crescente di moduli per la conversione tra i vari formati di file. Ci sono anche molte operazioni che si potrebbe voler effettuare sui dati (p.e. mixing, aggiunta di echi, applicazione di una funzione di equalizzazione, creazione di un effetto stereo artificiale), quindi si scriveranno via via una successione senza fine di moduli che effettuano tali operazioni. Ecco una possibile struttura per il package (espressa secondo un filesystem gerarchico):

Sound/                          Package principale
      __init__.py               Inizializza il package Sound
      Formats/                  Sottopackage per le conversioni tra formati
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      Effects/                  Sottopackage per gli effetti sonori
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      Filters/                  Sottopackage per i filtri
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

Quando il package viene importato, Python cerca all'interno delle directory in sys.path per controllare i package contenuti nelle sottodirectory.

I file __init__.py sono necessari per far sì che Python tratti correttamente le directory come contenitori di package; ciò viene fatto per evitare che directory con un nome comune, come "string", nascondano involontariamente moduli validi che le seguano nel percorso di ricerca dei moduli. Nel caso più semplice, __init__.py può essere un file vuoto, ma può anche eseguire codice di inizializzazione per il package oppure configurare la variabile __all__ descritta più avanti.

Gli utenti del package possono importare singoli moduli del package, per esempio:

import Sound.Effects.echo

Effettua il caricamento del sottomodulo Sound.Effects.echo. Dev'essere un riferimento al suo nome completo.

Sound.Effects.echo.echofilter(input, output, delay=0.7, atten=4)

Un modo alternativo per importare il sottomodulo è:

from Sound.Effects import echo

Anche questo carica il sottomodulo echo, e lo rende disponibile senza il prefisso del suo package, così da poter essere utilizzato nel seguente modo:

echo.echofilter(input, output, delay=0.7, atten=4)

Un'ulteriore variazione è importare direttamente la funzione o la variabile desiderata

from Sound.Effects.echo import echofilter

Di nuovo, questo carica il sottomodulo echo, ma questa volta rendendo la sua funzione echofilter() direttamente disponibile:

echofilter(input, output, delay=0.7, atten=4)

Si noti che, quando si usa from package import elemento, l'elemento può essere un sottomodulo (o sottopackage) del package o un altro nome definito nel package, come una funzione, una classe o una variabile. L'istruzione import per prima cosa si assicura che l'elemento sia definito nel package; se non lo è, assume che si tratti di un modulo e tenta di caricarlo. Se non lo trova, viene sollevata un'eccezione ImportError.

Al contrario, quando si usa una sintassi del tipo import elemento.sottoelemento.sottosottoelemento, ogni elemento eccetto l'ultimo dev'essere un package; l'ultimo può essere un modulo o un package ma non può essere una classe, una funzione o una variabile definita nell'elemento precedente.


6.4.1 Importare con * da un package

Ora, che succede quando l'utente scrive from Sound.Effects import*? Idealmente si spererebbe che in qualche modo questo si muova sul filesystem, trovi quali sottomoduli sono presenti nel package e li importi tutti. Sfortunatamente questa operazione non funziona molto bene sulle piattaforme Mac e Windows, dove il filesystem non sempre ha informazioni accurate sulle maiuscole e minuscole dei nomi di file! Su queste piattaforme non c'è un modo sicuro di sapere se un file ECHO.PY dovrebbe essere importato come modulo echo, Echo o ECHO. Ad esempio, Windows 95 ha la noiosa abitudine di mostrare tutti i nomi di file con la prima lettera maiuscola. La restrizione dei nomi di file a 8+3, caratteristica del DOS, aggiunge un altro problema interessante per nomi lunghi di moduli.

L'unica soluzione è che spetti all'autore fornire un indice esplicito del package. L'istruzione import adopera la seguente convenzione: se il codice del file __init__.py di un package definisce una lista di nome __all__, si assume che si tratti di una lista di nomi di moduli che devono essere importati quando viene incontrato un from package import *. È compito dell'autore del package mantenere aggiornata tale lista quando viene rilasciata una nuova versione. Gli autori dei package possono anche decidere di non supportare tale funzionalità se non vedono l'utilità di importare con * dal loro package. Per esempio, il file Sounds/Effects/__init__.py potrebbe contenere il codice seguente:

__all__ = ["echo", "surround", "reverse"]

Ciò significa che from Sound.Effects import * importerebbe i tre sottomoduli sopracitati del package Sound.

Se __all__ non viene definito, l'istruzione from Sound.Effects import * non importa tutti i sottomoduli del package Sound.Effects nello spazio dei nomi corrente; si assicura solamente che il package Sound.Effects sia stato importato (possibilmente eseguendo il suo codice di inizializzazione, __init__.py) e quindi importa qualunque nome sia definito nel package. Ciò include qualsiasi nome definito (e i sottomoduli esplicitamente caricati) in __init__.py. Comprende inoltre tutti i sottomoduli del package che siano stati esplicitamente caricati da precedenti istruzioni. Si consideri questo codice:

import Sound.Effects.echo
import Sound.Effects.surround
from Sound.Effects import *

In questo esempio, i moduli echo e surround sono importati nello spazio dei nomi corrente poiché vengono definiti nel package Sound.Effects al momento dell'esecuzione dell'istruzione from...import. Funziona così anche quando è definito __all__.

Si noti che in generale la pratica di importare con * da un modulo è malvista, dato che spesso comporta poca leggibilità del codice. Comunque è accettabile usarlo per risparmiare un po' di lavoro sulla tastiera nelle sessioni interattive, e certi moduli sono pensati per esportare solo nomi che seguono certi schemi.

Si tenga presente che non c'è nulla di sbagliato nell'uso di from Package import Uno_specifico_sottomodulo! Infatti questa è la notazione consigliata, a meno che il modulo importatore debba usare sottomoduli con lo stesso nome da package differenti.

6.4.2 Riferimenti interni ad un package

I sottomoduli spesso devono fare riferimento l'uno all'altro. Per esempio, il modulo surround potrebbe dover usare il modulo echo. In effetti tali riferimenti sono tanto comuni che l'istruzione import per prima cosa considera il package contenitore del modulo prima di effettuare una ricerca nel percorso standard di ricerca dei moduli. Perciò surround può semplicemente usare import echo o from echo import echofilter. Se il modulo importato non viene trovato nel package corrente (il package di cui il modulo corrente è un sottomodulo), l'istruzione import ricerca un modulo con quel nome al livello più alto.

Quando i package sono strutturati in sottopackage (come nel package Sound di esempio), non ci sono scorciatoie per riferirsi a package imparentati - dev'essere usato il nome completo del sottopackage. Per esempio, se il modulo Sound.Filters.vocoder vuole servirsi del modulo echo nel package Sound.Effects, può usare from Sound.Effects import echo.

6.4.3 Package in molteplici directory

I package supportano un attributo ancora più speciale, __path__. Viene inizializzato per essere una lista al cui interno risulti il nome della directory che contiene il package __init__.py prima che il codice in quel file sia eseguito. Questa variabile può essere modificata; in questo modo, avrà effetto su ricerche future dei moduli e dei sottopackage ivi contenuti.

Mentre questa caratteristica non è spesso necessaria, può essere usata per estendere l'insieme dei moduli trovati in un package.



Footnotes

... parte.6.1
In effetti le definizioni di funzione sono anche `istruzioni' che vengono `eseguite'; l'esecuzione inserisce il nome della funzione nella tabella dei simboli globale del modulo.
Vedete Circa questo documento... per informazioni su modifiche e suggerimenti.