> For the complete documentation index, see [llms.txt](https://exceedteam.gitbook.io/python-and-back-end/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://exceedteam.gitbook.io/python-and-back-end/python-language/moduli.md).

# Модули

Как можно использовать код повторно, помещая его в функции, мы уже видели. А что, если нам понадобится повторно использовать различные функции в других наших программах? Как вы уже, наверное, догадались, ответ – модули.

Существуют разные способы составления модулей, но самый простой – это создать файл с расширением `.py`, содержащий функции и переменные.

Другой способ – написать модуль на том языке программирования, на котором написан сам интерпретатор Python. Например, можно писать модули на языке программирования C, которые после компиляции могут использоваться стандартным интерпретатором Python.

Модуль можно *импортировать* в другую программу, чтобы использовать функции из него. Точно так же мы используем стандартную библиотеку Python. Сперва посмотрим, как использовать модули стандартной библиотеки.

**Пример:** (сохраните как `using_sys.py`)

```python
import sys

print('Аргументы командной строки:')
for i in sys.argv:
    print(i)

print('\n\nПеременная PYTHONPATH содержит', sys.path, '\n')
```

**Вывод:**

```python
$ python3 using_sys.py we are arguments
Аргументы командной строки:
using_sys.py
we
are
arguments

Переменная PYTHONPATH содержит ['', 'C:\\Windows\\system32\\python30.zip',
'C:\\Python30\\DLLs', 'C:\\Python30\\lib',
'C:\\Python30\\lib\\plat-win', 'C:\\Python30',
'C:\\Python30\\lib\\site-packages']
```

**Как это работает:**

> В начале мы *импортируем* модуль `sys` командой `import`. Этим мы говорим Python, что хотим использовать этот модуль. Модуль `sys` содержит функции, относящиеся к интерпретатору Python и его среде, т.е. к **сис**теме (**sys**tem).
>
> Когда Python выполняет команду `import sys`, он ищет модуль `sys`. В данном случае это один из встроенных модулей, и Python знает, где его искать.
>
> Если бы это был не скомпилированный модуль, т.е. модуль, написанный на Python, тогда интерпретатор Python искал бы его в каталогах, перечисленных в переменной `sys.path`. Если модуль найден, выполняются команды в теле модуля, и он становится *доступным*. Обратите внимание, что инициализация происходит только при *первом* импорте модуля.
>
> Доступ к переменной `argv` в модуле `sys` предоставляется при помощи точки, т.е. `sys.argv`. Это явно показывает, что это имя является частью модуля `sys`. Ещё одним преимуществом такого обозначения является то, что имя не конфликтует с именем переменной `argv`, которая может использоваться в вашей программе.
>
> Переменная `sys.argv` является *списком* строк она содержит список *аргументов командной строки*, т.е. аргументов, переданных программе из командной строки.
>
> Если вы используете среду разработки для написания и запуска программ, поищите где-нибудь в её меню возможность передавать параметры командной строки.
>
> В нашем примере, когда мы запускаем “`python using_sys.py we are arguments`”, мы запускаем модуль `using_sys.py` командой `python`, а всё, что следует далее – аргументы, передаваемые программе. Python сохраняет аргументы командной строки в переменной `sys.argv` для дальнейшего использования.
>
> Помните, что имя запускаемого сценария всегда является первым аргументом в списке `sys.argv`. Так что в приведённом примере `'using_sys.py'` будет элементом `sys.argv[0]`, `'we'` – `sys.argv[1]`, `'are'` – `sys.argv[2]`, а `'arguments'` – `sys.argv[3]`. Помните, что в Python нумерация начинается с 0, а не с 1.
>
> `sys.path` содержит список имён каталогов, откуда импортируются модули. Заметьте, что первая строка в `sys.path` пуста; эта пустая строка показывает, что текущая директория также является частью `sys.path`, которая совпадает со значением переменной окружения `PYTHONPATH`. Это означает, что модули, расположенные в текущем каталоге, можно импортировать напрямую. В противном случае придётся поместить свой модуль в один из каталогов, перечисленных в `sys.path`.
>
> Помните, что текущий каталог – это каталог, в котором была запущена программа. Выполните “`import os; print(os.getcwd())`”, чтобы узнать текущий каталог программы.

### Оператор from ... import ...

Чтобы импортировать переменную `argv` прямо в программу и не писать всякий раз `sys.` при обращении к ней, можно воспользоваться выражением “`from sys import argv`”.

Для импорта всех имён, использующихся в модуле `sys`, можно выполнить команду “`from sys import *`”. Это работает для любых модулей.

В общем случае вам *следует избегать* использования этого оператора и использовать вместо этого оператор `import`, чтобы предотвратить конфликты имён и не затруднять чтение программы.

**Пример:**

```python
from math import *
n = int(input("Введите диапазон:-  "))
p = [2, 3]
count = 2
a = 5
while (count < n):
    b=0
    for i in range(2,a):
        if ( i <= sqrt(a)):
            if (a % i == 0):
                print(a,"непростое")
                b = 1
            else:
                pass

    if (b != 1):
        print(a,"простое")
        p = p + [a]
    count = count + 1
    a = a + 2
print(p)
```

### Имя модуля – \_\_name\_\_

У каждого модуля есть имя, и команды в модуле могут узнать имя их модуля. Это полезно, когда нужно знать, запущен ли модуль как самостоятельная программа или импортирован. Как уже упоминалось выше, когда модуль импортируется впервые, содержащийся в нём код исполняется. Мы можем воспользоваться этим для того, чтобы заставить модуль вести себя по-разному в зависимости от того, используется ли он сам по себе или импортируется в другую программа. Этого можно достичь с применением атрибута модуля под названием `__name__`.

**Пример:** (сохраните как `using_name.py`)

```python
if __name__ == '__main__':
    print('Эта программа запущена сама по себе.')
else:
    print('Меня импортировали в другой модуль.')
```

**Вывод:**

```python
$ python3 using_name.py
Эта программа запущена сама по себе.

$ python3
>>> import using_name
Меня импортировали в другой модуль.
>>>
```

**Как это работает:**

> В каждом модуле Python определено его имя – `__name__`. Если оно равно `'__main__'`, это означает, что модуль запущен самостоятельно пользователем, и мы можем выполнить соответствующие действия.

### Создание собственных модулей

Создать собственный модуль очень легко. Да вы всё время делали это! Ведь каждая программа на Python также является и модулем. Необходимо лишь убедиться, что у неё установлено расширение `.py`. Следующий пример объяснит это.

**Пример:** (сохраните как `mymodule.py`)

```python
def sayhi():
    print('Привет! Это говорит мой модуль.')

__version__ = '0.1'

# Конец модуля mymodule.py
```

Выше приведён простой *модуль*. Как видно, в нём нет ничего особенного по сравнению с обычной программой на Python. Далее посмотрим, как использовать этот модуль в других наших программах.

Помните, что модуль должен находиться либо в том же каталоге, что и программа, в которую мы импортируем его, либо в одном из каталогов, указанных в `sys.path`.

Ещё один модуль (сохраните как `mymodule_demo.py`):

```python
import mymodule

mymodule.sayhi()
print ('Версия', mymodule.__version__)
```

**Вывод:**

```python
$ python mymodule_demo.py
Привет! Это говорит мой модуль.
Версия 0.1
```

Вот версия, использующая синтаксис `from..import` (сохраните как `mymodule_demo2.py`):

```python
from mymodule import sayhi, __version__

sayhi()
print('Версия', __version__)
```

Вывод `mymodule_demo2.py` такой же, как и `mymodule_demo.py`.

Обратите внимание, что если в модуле, импортирующем данный модуль, уже было объявлено имя `__version__`, возникнет конфликт. Это весьма вероятно, так как объявлять версию любого модуля при помощи этого имени – общепринятая практика. Поэтому всегда рекомендуется отдавать предпочтение оператору `import`, хотя это и сделает вашу программу немного длиннее.

Вы могли бы также использовать:

```python
from mymodule import *
```

Это импортирует все публичные имена, такие как `sayhi`, но не импортирует `__version__`, потому что оно начинается с двойного подчёркивания

### Функция dir

Встроенная функция `dir()` возвращает список имён, определяемых объектом. Например, для модуля в этот список входят функции, классы и переменные, определённые в этом модуле.

Эта функция может принимать аргументы. Если в качестве аргумента указано имя модуля, она возвращает список имён, определённых в этом модуле. Если никакого аргумента не передавать, она вернёт список имён, определённых в текущем модуле.

**Пример:**

```python
$ python3

>>> import sys # получим список атрибутов модуля 'sys'

>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__package__', '__s
tderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_compact_freelists',
'_current_frames', '_getframe', 'api_version', 'argv', 'builtin_module_names', '
byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle'
, 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable',
'exit', 'flags', 'float_info', 'getcheckinterval', 'getdefaultencoding', 'getfil
esystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof',
'gettrace', 'getwindowsversion', 'hexversion', 'intern', 'maxsize', 'maxunicode
', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platfor
m', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setprofile', 'setrecursionlimit
', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_in
fo', 'warnoptions', 'winver']

>>> dir() # получим список атрибутов текущего модуля
['__builtins__', '__doc__', '__name__', '__package__', 'sys']

>>> a = 5 # создадим новую переменную 'a'

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'a', 'sys']

>>> del a # удалим имя 'a'

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'sys']

>>>
```

**Как это работает:**

> Сперва мы видим результат применения `dir` к импортированному модулю `sys`. Видим огромный список атрибутов, содержащихся в нём.
>
> Затем мы вызываем функцию `dir`, не передавая ей параметров. По умолчанию, она возвращает список атрибутов текущего модуля. Обратите внимание, что список импортированных модулей также входит туда.
>
> Чтобы пронаблюдать за действием `dir`, мы определяем новую переменную `a` и присваиваем ей значение, а затем снова вызываем `dir`. Видим, что в полученном списке появилось дополнительное значение. Удалим переменную/атрибут из текущего модуля при помощи оператора `del`, и изменения вновь отобразятся на выводе функции `dir`.
>
> Замечание по поводу `del`: этот оператор используется для *удаления* переменной/имени, и после его выполнения, в данном случае – `del a`, к переменной `a` больше невозможно обратиться – её как будто никогда и не было.
>
> Обратите внимание, что функция `dir()` работает для *любого* объекта. Например, выполните “`dir('print')`”, чтобы увидеть атрибуты функции `print`, или “`dir(str)`”, чтобы увидеть атрибуты класса `str`.

### Пакеты

К настоящему времени вы, вероятно, начали наблюдать некоторую иерархию в организации ваших программ. Переменные обычно находятся в функциях. Функции и глобальные переменные обычно находятся в модулях. А что, если возникнет необходимость как-то организовать модули? Вот здесь-то и выходят на сцену пакеты.

Пакеты – это просто каталоги с модулями и специальным файлом `__init__.py`, который показывает Python, что этот каталог особый, так как содержит модули Python.

Представим, что мы хотим создать пакет под названием “world” с субпакетами “asia”, “africa” и т.д., которые, в свою очередь, будут содержать модули “india”, “madagascar” и т.д.

Для этого следовало бы создать следующую структуру каталогов:

```python
| - <некоторый каталог из sys.path>/
| |---- world/
|      |---- __init__.py
|      |---- asia/
|      |    |---- __init__.py
|      |    |---- india/
|      |         |---- __init__.py
|      |         |---- foo.py
|      |---- africa/
|           |---- __init__.py
|           |---- madagascar/
|                |---- __init__.py
|                |---- bar.py
```

Пакеты – это удобный способ иерархически организовать модули.
