2.19. Написання модулів¶
Будь-який файл .py є модулем. Розподіл зростаючого скрипту між кількома файлами зменшує розмір кожного файлу та дозволяє спільно використовувати допоміжні функції між скриптами.
2.19.1. Розбиття скрипту¶
Виділіть пов’язану групу функцій в окремий файл:
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"))
Виведення:
OpenMV
[ready]
Два файли знаходяться поруч в одному каталозі. Коли запускається main.py, import camera_utils читає camera_utils.py один раз, виконує його операції верхнього рівня та прив’язує отриманий об’єкт модуля до імені camera_utils у main. Повторний import camera_utils з будь-якого місця повертає той самий об’єкт – модулі кешуються після першого завантаження.
Ім’я модуля береться з імені файлу, тому camera_utils.py імпортується як import camera_utils.
2.19.2. Багатофайлові модулі (пакети)¶
Модуль також може бути каталогом файлів, а не одним файлом .py. Ім’я каталогу стає іменем модуля, а файли всередині – його підмодулями:
camera_utils/
__init__.py
text.py
timing.py
__init__.py – це файл, що виконується при імпорті самого пакету; він може бути порожнім або реекспортувати вибрані імена з підмодулів. Підмодулі доступні за пунктирним ім’ям:
import camera_utils.text
from camera_utils.timing import elapsed
camera_utils.text.label("ready")
Всередині пакету підмодулі можуть звертатися один до одного або за повним пунктирним іменем, або за допомогою відносного імпорту з провідною крапкою, що означає «цей пакет»:
camera_utils/timing.py
from . import text # the sibling submodule
def stamp(value):
return text.label(str(value))
Щоб імпортувати конкретне ім’я, вкажіть його після пунктирного імені підмодуля:
from .text import label
def stamp(value):
return label(str(value))
Відносні імпорти роблять пакет самодостатнім: перейменування каталогу пакету не вимагає редагування кожного підмодуля.
Використовуйте пакет, коли окремий файл стає надто великим, або коли набір пов’язаних модулів логічно належить до одного простору імен. Для повсякденних скриптів достатньо одного файлу .py.
2.19.3. Захист __name__¶
Кожен модуль має вбудоване ім’я __name__. Його значення залежить від способу використання файлу:
Коли файл запускається безпосередньо,
__name__встановлюється в рядок"__main__".Коли файл імпортується іншим скриптом,
__name__встановлюється в ім’я модуля – ім’я файлу без.py.
Використовуваний ідіом виглядає так:
label_util.py
def label(text):
return "[" + text + "]"
if __name__ == "__main__":
print(label("self-test"))
Виведення (при безпосередньому запуску):
[self-test]
Коли той самий файл імпортується, __name__ встановлюється в ім’я модуля, тому блок if пропускається і нічого зайвого не виконується:
>>> import label_util
>>> label_util.__name__
'label_util'
Використовуйте цей шаблон для додавання швидкого тесту або демонстрації до бібліотечного файлу, не порушуючи роботу скриптів, що його імпортують.