2.19. Scrivere i moduli¶
Qualsiasi file .py è un modulo. Suddividere uno script in crescita su alcuni file mantiene ogni file breve e consente di condividere helper comuni tra gli script.
2.19.1. Suddividere uno script¶
Estrai un gruppo correlato di funzioni in un proprio file:
camera_utils.py
def banner():
print("OpenMV")
def label(text):
return "[" + text + "]"
main.py
import camera_utils
camera_utils.banner()
print(camera_utils.label("ready"))
Output:
OpenMV
[ready]
I due file stanno fianco a fianco nella stessa directory. Quando main.py viene eseguito, import camera_utils legge camera_utils.py una volta, esegue le sue istruzioni di livello superiore e lega l’oggetto modulo risultante al nome camera_utils in main. Un secondo import camera_utils da qualsiasi altro punto restituisce lo stesso oggetto – i moduli vengono memorizzati nella cache dopo il loro primo caricamento.
Il nome di un modulo deriva dal suo nome di file, quindi camera_utils.py viene importato come import camera_utils.
2.19.2. Moduli multi-file (pacchetti)¶
Un modulo può anche essere una directory di file anziché un singolo .py. Il nome della directory diventa il nome del modulo, e i file al suo interno sono i suoi sottomoduli:
camera_utils/
__init__.py
text.py
timing.py
__init__.py è il file che viene eseguito quando il pacchetto stesso viene importato; può essere vuoto, oppure può riesportare nomi selezionati dai sottomoduli. I sottomoduli si raggiungono con un nome puntato:
import camera_utils.text
from camera_utils.timing import elapsed
camera_utils.text.label("ready")
All’interno del pacchetto, i sottomoduli possono raggiungersi a vicenda sia con il nome puntato completo sia con un import relativo che usa un punto iniziale per indicare «questo pacchetto»:
camera_utils/timing.py
from . import text # the sibling submodule
def stamp(value):
return text.label(str(value))
Per importare invece un nome specifico, indicalo dopo il fratello puntato:
from .text import label
def stamp(value):
return label(str(value))
Gli import relativi mantengono un pacchetto autonomo: rinominare la directory del pacchetto non richiede di modificare ogni sottomodulo.
Usa un pacchetto quando un singolo file cresce oltre una dimensione comoda, o quando un insieme di moduli correlati deve stare insieme sotto un unico namespace. Per gli script di tutti i giorni un singolo file .py è sufficiente.
2.19.3. La guardia __name__¶
Ogni modulo ha un nome integrato __name__. Il suo valore dipende da come viene usato il file:
Quando il file viene eseguito direttamente,
__name__è impostato alla stringa"__main__".Quando il file viene importato da un altro script,
__name__è impostato al nome del modulo – il nome del file senza.py.
L’idioma che sfrutta questo è:
label_util.py
def label(text):
return "[" + text + "]"
if __name__ == "__main__":
print(label("self-test"))
Output (quando eseguito direttamente):
[self-test]
Quando lo stesso file viene invece importato, __name__ è impostato al nome del modulo, quindi il blocco if viene saltato e non viene eseguito nulla di aggiuntivo:
>>> import label_util
>>> label_util.__name__
'label_util'
Usa questo schema per allegare un rapido smoke test o una demo a un file di libreria senza disturbare gli script che lo importano.