loading...

08.05.2020

Уроки Python: модули, пакеты. Правильно организуем код.

В данной статье мы рассмотрим принцип организации (и разбиения) кода в проекте на Python. Основные понятия, которые мы узнаем — это «пакет» и «модуль», далее мы детально разберём что они значат.

Модули

В любом проекте в определённый момент появляются участки кода, которые с некоторой периодичностью повторяются. Обычно такой код переделывают в функцию и вызывают её в нужных местах. Вот как раз файл, который содержит функции (или классы, или просто Python код) и называется модулем. Т.е. модуль — это просто файл (.py), содержащий код на Python (например, функции, классы, переменные и т.д.). Но что делать дальше, после создания модуля (например, simple_module.py)? Ведь нам надо как-то использовать тот код, который мы написали в модуле. И тут нам на помощь приходят ключевые слова (команды): import … и from … import … , давайте рассмотрим их.

import

Ключевое слово import позволяет нам импортировать (т.е. даёт доступ) модуль и после этого работать с функциями, классами, переменными, которые объявлены в этом модуле.
Давайте попробуем создать модуль simple_module.py и файл main.py, в котором мы будем импортировать наш модуль.
Листинг 1.1 (simple_module.py):

def say_hello(name):
    print('Hello {}!'.format(name))
 
def say_bye(name):
    print('Bye {}!'.format(name))
 
def say_wtf(name):
    print('WTF {}?!'.format(name))
 
 
if __name__ == '__main__':
    say_hello('Ivan')
    say_bye('Ivan')
    say_wtf('Ivan')

Листинг 1.2 (main.py):

import simple_module
 
simple_module.say_hello('Vladimir')
simple_module.say_bye('Vladimir')
simple_module.say_wtf('Vladimir')

В файле simple_module.py (наш модуль) мы объявили 3 функции, как видим — файл simple_module.py у нас играет роль некой «библиотеки» с функциями, зачастую в этом и заключается роль модулей. А благодаря строке 11 нашего модуля мы можем использовать его обособленно от проекта (например запустить какой-то код). Дело в том что глобальная переменная __name__ будет равна __main__ если мы запустим скрипт simple_module.py из консоли (находясь в папке с этим файлом):
python simple_module.py
И в таком случае будет выполнен код из блока if.

Рассмотрим листинг 1.2. В файле main.py первая строка импортирует наш модуль (т.е. всё что написано внутри него нам становится доступно в файле main.py). А ниже в строках 3, 4, 5 мы вызываем 3 функции из модуля simple_module. При импорте модуля глобальная переменная __name__ равна названию модуля, т.е. simple_module и код из блока if в таком случае не будет выполнен.
Если сейчас выполнить:
python3 main.py
То вы увидите следующую картину:
Hello Vladimir!
Bye Vladimir!
WTF Vladimir?!

Как видим — код выполнился корректно.

from … import …

Давайте теперь рассмотрим конструкцию from … import … . Для чего она, если есть просто import ? Всё просто — import импортирует ВЕСЬ модуль, т.е. становятся доступны ВСЕ функции/классы/переменные из модуля. В то время как from … import … импортирует из модуля только нужные нам объекты (функции, классы, переменные).
Оставим simple_module.py таким же, а вот main.py немного изменим.
Листинг 2.1 (main.py)

from simple_module import say_hello, say_bye
 
say_hello('Vladimir')
say_bye('Vladimir')

Здесь всё почти так же, главное отличие — мы импортировали из модуля simple_module отдельные 2 функции, а не все 3. Если вы попробуете в main.py добавить код вызова функции say_wtf, то программа упадёт с ошибкой:

Traceback (most recent call last):
  File "main.py", line 5, in <module>
    say_wtf('Vladimir')
NameError: name 'say_wtf' is not defined

Так как функцию say_wtf из нашего модуля мы не импортировали.

from … import *

Отдельного упоминания заслуживает конструкция from … import * . Она выполняет те же действия что и предыдущая конструкция, но импортирует ВСЕ объекты (функции/классы/переменные) из модуля.
Изменим наш main.py
Листинг 3.1 (main.py)

from simple_module import *
 
say_hello('Vladimir')
say_bye('Vladimir')
say_wtf('Vladimir')

Теперь наш код корректно работает и не падает с ошибкой, так как были импортированы все функции из нашего модуля.
Но старайтесь пользоваться данной конструкцией всё же как можно реже и очень аккуратно, так как она «засоряет» текущее пространство имён и могут возникнуть проблемы с кодом (особенно если в модуле есть объекты, которые называются так же, как у вас уже называются ваши собственные объекты).

Как назвать модуль?

Как мы уже выяснили — модуль обычно используется как некоторая библиотека функций (или классов), и поэтому называть его лучше с учётом функционала, который он предоставляет. Например, наш модуль simple_module можно было бы назвать say, так как в нём хранятся функции связанные с say.
Вот основные правило именования модулей:

  • Нельзя называть модуль ключевым словом (например, import). Список ключевых слов можно посмотреть тут.
  • Также не стоит называть модуль как встроенную функцию, так как это создаст проблемы при использовании функций. Список таких функций можно посмотреть тут.
  • Нельзя начинать название модуля с цифры.

Вот ещё небольшая помощь по именованию модулей:

identifier ::=  (letter|"_") (letter | digit | "_")*

Пакеты

Пакет — это фактически просто папка с модулями (хотя можно создать пакет и без модулей) и файлом __init__.py (хотя вроде с версии Python 3.3 уже не обязательно создавать этот файл).
Давайте попробуем создать пакет. Для начала надо создать вот такую структуру файлов:

say/
    __init__.py
    human.py
    cat.py
    dog.py
main.py

Теперь запишем код в файлы.
Листинг 4.1 (human.py):

def say():
    print('Hello!')

Листинг 4.2 (cat.py):

def say():
    print('Meow!')

Листинг 4.3 (dog.py):

def say():
    print('Waf!')

Листинг 4.4 (main.py):

from say import human, cat, dog

human.say()
cat.say()
dog.say()

Данный код выведет:
Hello!
Meow!
Waf!


Так же мы можем импортировать конкретные функции из модулей пакета say.
Листинг 4.5 (main.py):

from say.human import say as say_human
from say.cat import say as say_cat
from say.dog import say as say_dog

say_human()
say_cat()
say_dog()

В данном коде мы воспользовались конструкцией from … import … as … , так как наши функции называются в каждом модуле одинаково (say) и чтобы они не «перекрывали» друг друга — мы их импортируем под другим именем.

from МОДУЛЬ import ФУНКЦИЯ as НОВОЕ_ИМЯ

Вот примерно так.

На этом всё, а в следующей статье мы поговорим о том где Python ищет модули и пакеты, как можно узнать больше информации о модуле или пакете и научимся всё же загружать модули из пакета с помощью команды from ПАКЕТ import * .

Ну и в заключении — если у вас есть замечания или вопросы по данной статье, то пишите об этом в комментариях или мне в социальных сетях (ссылки указаны в нижней части сайта).

Posted in Python, БлогTaggs:
Write a comment