2.19. Pisanje modula

Svaka .py datoteka je modul. Dijeljenje rastuće skripte na nekoliko datoteka održava svaku datoteku kratkom i omogućuje dijeljenje zajedničkih pomoćnika među skriptama.

2.19.1. Dijeljenje skripte

Izvucite povezanu skupinu funkcija u njihovu vlastitu datoteku:

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"))

Izlaz:

OpenMV
[ready]

Dvije datoteke stoje jedna pokraj druge u istom direktoriju. Kada se main.py pokrene, import camera_utils jednom pročita camera_utils.py, izvrši njegove naredbe na najvišoj razini i poveže nastali objekt modula s imenom camera_utils u main. Drugi import camera_utils s bilo kojeg drugog mjesta vraća isti objekt – moduli se predmemoriraju nakon prvog učitavanja.

Ime modula dolazi iz njegova naziva datoteke, pa se camera_utils.py uvozi kao import camera_utils.

2.19.2. Višedatotečni moduli (paketi)

Modul može biti i direktorij datoteka, a ne pojedinačna .py. Ime direktorija postaje ime modula, a datoteke unutar njega njegovi su podmoduli:

camera_utils/
    __init__.py
    text.py
    timing.py

__init__.py je datoteka koja se izvršava kada se sam paket uveze; može biti prazna ili može ponovno izvoziti odabrana imena iz podmodula. Podmoduli se dosežu pomoću točkovnog imena:

import camera_utils.text
from camera_utils.timing import elapsed

camera_utils.text.label("ready")

Unutar paketa, podmoduli mogu doseći jedan drugoga ili punim točkovnim imenom ili relativnim uvozom koji koristi vodeću točku da označi „ovaj paket”:

camera_utils/timing.py

from . import text             # the sibling submodule

def stamp(value):
    return text.label(str(value))

Za uvlačenje određenog imena umjesto toga, imenujte ga prema točkovnom sljedu:

from .text import label

def stamp(value):
    return label(str(value))

Relativni uvozi održavaju paket samostalnim: preimenovanje direktorija paketa ne zahtijeva uređivanje svakog podmodula.

Koristite paket kada jedna datoteka naraste preko ugodne veličine, ili kada skup povezanih modula pripada zajedno pod jednim prostorom imena. Za svakodnevne skripte dovoljna je jedna .py datoteka.

2.19.3. Zaštita __name__

Svaki modul ima ugrađeno ime __name__. Njegova vrijednost ovisi o tome kako se datoteka koristi:

  • Kada se datoteka pokrene izravno, __name__ se postavlja na niz "__main__".

  • Kada se datoteka uveze iz druge skripte, __name__ se postavlja na ime modula – naziv datoteke bez .py.

Idiom koji to koristi jest:

label_util.py

def label(text):
    return "[" + text + "]"

if __name__ == "__main__":
    print(label("self-test"))

Izlaz (kada se pokrene izravno):

[self-test]

Kada se ista datoteka umjesto toga uveze, __name__ se postavlja na ime modula, pa se if blok preskače i ništa dodatno se ne izvršava:

>>> import label_util
>>> label_util.__name__
'label_util'

Koristite ovaj obrazac da biste priložili brzi dimni test ili demo datoteci biblioteke bez ometanja skripti koje je uvoze.