2.19. Escrever módulos

Qualquer ficheiro .py é um módulo. Dividir um script crescente por vários ficheiros mantém cada ficheiro curto e permite que auxiliares comuns sejam partilhados entre scripts.

2.19.1. Dividir um script

Retire um grupo relacionado de funções para o seu próprio ficheiro:

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

Saída:

OpenMV
[ready]

Os dois ficheiros ficam lado a lado no mesmo diretório. Quando main.py é executado, import camera_utilscamera_utils.py uma vez, executa as suas instruções de nível superior e associa o objeto módulo resultante ao nome camera_utils em main. Um segundo import camera_utils a partir de qualquer outro lugar devolve o mesmo objeto – os módulos são colocados em cache após a sua primeira carga.

O nome de um módulo vem do seu nome de ficheiro, por isso camera_utils.py é importado como import camera_utils.

2.19.2. Módulos com vários ficheiros (pacotes)

Um módulo pode também ser um diretório de ficheiros em vez de um único .py. O nome do diretório torna-se o nome do módulo, e os ficheiros dentro são os seus submódulos:

camera_utils/
    __init__.py
    text.py
    timing.py

__init__.py é o ficheiro que é executado quando o pacote em si é importado; pode estar vazio, ou pode re-exportar nomes selecionados dos submódulos. Os submódulos são acessíveis com um nome com ponto:

import camera_utils.text
from camera_utils.timing import elapsed

camera_utils.text.label("ready")

Dentro do pacote, os submódulos podem aceder uns aos outros quer pelo nome completo com ponto, quer por uma importação relativa que usa um ponto inicial para significar «este pacote»:

camera_utils/timing.py

from . import text             # the sibling submodule

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

Para importar um nome específico, nomeie-o depois do irmão com ponto:

from .text import label

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

As importações relativas mantêm um pacote autocontido: renomear o diretório do pacote não requer editar cada submódulo.

Use um pacote quando um único ficheiro cresce além de um tamanho confortável, ou quando um conjunto de módulos relacionados pertence a um único espaço de nomes. Para scripts do quotidiano, um único ficheiro .py é suficiente.

2.19.3. O guarda __name__

Todos os módulos têm um nome integrado __name__. O seu valor depende de como o ficheiro está a ser utilizado:

  • Quando o ficheiro é executado diretamente, __name__ é definido com a string "__main__".

  • Quando o ficheiro é importado por outro script, __name__ é definido com o nome do módulo – o nome do ficheiro sem .py.

O idioma que utiliza isto é:

label_util.py

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

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

Saída (quando executado diretamente):

[self-test]

Quando o mesmo ficheiro é importado em vez de executado, __name__ é definido com o nome do módulo, pelo que o bloco if é ignorado e não é executado mais nada:

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

Use o padrão para associar um teste rápido ou demonstração a um ficheiro de biblioteca sem perturbar os scripts que o importam.