# 6. Модулі

Якщо ви вийшли з інтерпретатора Python і ввели його знову, зроблені вами визначення (функції та змінні) буде втрачено. Тому, якщо ви хочете написати дещо довшу програму, вам краще використовувати текстовий редактор, щоб підготувати вхідні дані для інтерпретатора, а замість цього запустити її з цим файлом як вхідними. Це відоме як створення сценарію. Коли ваша програма стає довшою, ви можете розділити її на кілька файлів для полегшення обслуговування. Ви також можете використати зручну функцію, яку ви написали в кількох програмах, не копіюючи її визначення в кожну програму.

Для підтримки цього Python має спосіб помістити визначення у файл і використовувати їх у сценарії або в інтерактивному екземплярі інтерпретатора. Такий файл називається модулем; визначення з модуля можна імпортувати в інші модулі або в головний модуль (набір змінних, до яких ви маєте доступ у сценарії, що виконується на верхньому рівні та в режимі калькулятора).

Модуль — це файл, що містить визначення та оператори Python. Ім’я файлу — це ім’я модуля з суфіксом `.py`. У межах модуля ім’я модуля (у вигляді рядка) доступне як значення глобальної змінної `__name__`. Наприклад, скористайтеся своїм улюбленим текстовим редактором, щоб створити файл під назвою `fibo.py` у поточному каталозі з таким вмістом:

    # Fibonacci numbers module

    def fib(n):    # write Fibonacci series up to n
        a, b = 0, 1
        while a < n:
            print(a, end=' ')
            a, b = b, a+b
        print()

    def fib2(n):   # return Fibonacci series up to n
        result = []
        a, b = 0, 1
        while a < n:
            result.append(a)
            a, b = b, a+b
        return result

Тепер увійдіть до інтерпретатора Python та імпортуйте цей модуль за допомогою наступної команди:

    >>> import fibo

This does not add the names of the functions defined in `fibo` directly to the current namespace (see Області та простори імен Python for more details); it only adds the module name `fibo` there. Using the module name you can access the functions:

    >>> fibo.fib(1000)
    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
    >>> fibo.fib2(100)
    [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    >>> fibo.__name__
    'fibo'

Якщо ви маєте намір часто використовувати функцію, ви можете призначити їй локальну назву:

    >>> fib = fibo.fib
    >>> fib(500)
    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

## 6.1. Детальніше про модулі

Модуль може містити виконувані оператори, а також визначення функцій. Ці оператори призначені для ініціалізації модуля. Вони виконуються лише вперше, коли ім’я модуля зустрічається в операторі імпорту. [1] (Вони також запускаються, якщо файл виконується як сценарій.)

Each module has its own private namespace, which is used as the global namespace by all functions defined in the module. Thus, the author of a module can use global variables in the module without worrying about accidental clashes with a user’s global variables. On the other hand, if you know what you are doing you can touch a module’s global variables with the same notation used to refer to its functions, `modname.itemname`.

Modules can import other modules. It is customary but not required to place all `import` statements at the beginning of a module (or script, for that matter). The imported module names, if placed at the top level of a module (outside any functions or classes), are added to the module’s global namespace.

There is a variant of the `import` statement that imports names from a module directly into the importing module’s namespace. For example:

    >>> from fibo import fib, fib2
    >>> fib(500)
    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

This does not introduce the module name from which the imports are taken in the local namespace (so in the example, `fibo` is not defined).

Існує навіть варіант імпорту всіх імен, які визначає модуль:

    >>> from fibo import *
    >>> fib(500)
    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Це імпортує всі імена, крім тих, що починаються з підкреслення (`_`). У більшості випадків програмісти Python не використовують цю можливість, оскільки вона вводить невідомий набір імен в інтерпретатор, можливо, приховуючи деякі речі, які ви вже визначили.

Зауважте, що загалом практика імпортування `*` з модуля чи пакету викликає негативне ставлення, оскільки це часто призводить до поганої читабельності коду. Однак його можна використовувати, щоб не вводити текст під час інтерактивних сеансів.

Якщо ім’я модуля супроводжується `as`, тоді ім’я після `as` прив’язується безпосередньо до імпортованого модуля.

    >>> import fibo as fib
    >>> fib.fib(500)
    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Це фактично імпортує модуль таким же чином, як і `import fibo`, з тією лише різницею, що він доступний як `fib`.

Його також можна використовувати при використанні `from` з подібними ефектами:

    >>> from fibo import fib as fibonacci
    >>> fibonacci(500)
    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Примітка

З міркувань ефективності кожен модуль імпортується лише один раз за сеанс інтерпретатора. Таким чином, якщо ви змінюєте свої модулі, ви повинні перезапустити інтерпретатор – або, якщо це лише один модуль, який ви хочете протестувати в інтерактивному режимі, використайте `importlib.reload()`, напр. `імпорт importlib; importlib.reload(modulename)`.

### 6.1.1. Виконання модулів у вигляді скриптів

Коли ви запускаєте модуль Python з

    python fibo.py <arguments>

код у модулі буде виконано так само, як якщо б ви його імпортували, але з `__name__` встановленим на `"__main__"`. Це означає, що додавши цей код у кінці вашого модуля:

    if __name__ == "__main__":
        import sys
        fib(int(sys.argv[1]))

ви можете зробити файл придатним для використання як сценарій, а також як імпортований модуль, оскільки код, який аналізує командний рядок, запускається, лише якщо модуль виконується як «основний» файл:

    $ python fibo.py 50
    0 1 1 2 3 5 8 13 21 34

Якщо модуль імпортовано, код не виконується:

    >>> import fibo
    >>>

Це часто використовується або для забезпечення зручного інтерфейсу користувача для модуля, або для цілей тестування (запуск модуля як сценарію виконує набір тестів).

### 6.1.2. Шлях пошуку модуля

When a module named `spam` is imported, the interpreter first searches for a built-in module with that name. These module names are listed in `sys.builtin_module_names`. If not found, it then searches for a file named `spam.py` in a list of directories given by the variable `sys.path`. `sys.path` is initialized from these locations:

- Каталог, що містить вхідний сценарій (або поточний каталог, якщо файл не вказано).

- `PYTHONPATH` (список імен каталогів із тим самим синтаксисом, що й змінна оболонки `PATH`).

- Типове значення, що залежить від встановлення (за домовленістю включає каталог `site-packages`, який обробляється модулем `site`).

More details are at The initialization of the sys.path module search path.

Примітка

У файлових системах, які підтримують символічні посилання, каталог, що містить вхідний сценарій, обчислюється після переходу за символічним посиланням. Іншими словами, каталог, що містить символічне посилання, не додається до шляху пошуку модуля.

Після ініціалізації програми Python можуть змінювати `sys.path`. Каталог, що містить запущений скрипт, розміщується на початку шляху пошуку, перед стандартним шляхом до бібліотеки. Це означає, що скрипти в цьому каталозі будуть завантажені замість однойменних модулів у каталозі бібліотеки. Це помилка, якщо заміна не призначена. Перегляньте розділ Стандартні модулі для отримання додаткової інформації.

### 6.1.3. «Компільовані» файли Python

Щоб прискорити завантаження модулів, Python кешує скомпільовану версію кожного модуля в каталозі `__pycache__` під назвою `module.version.pyc`, де версія кодує формат скомпільованого файлу; зазвичай містить номер версії Python. Наприклад, у випуску CPython 3.3 скомпільована версія spam.py буде кешована як `__pycache__/spam.cpython-33.pyc`. Ця угода про іменування дозволяє співіснувати скомпільованим модулям з різних випусків і різних версій Python.

Python порівнює дату модифікації вихідного коду зі скомпільованою версією, щоб перевірити, чи вона застаріла та потребує перекомпіляції. Це повністю автоматичний процес. Крім того, скомпільовані модулі не залежать від платформи, тому одна й та сама бібліотека може використовуватися між системами з різними архітектурами.

Python не перевіряє кеш у двох випадках. По-перше, він завжди перекомпілює і не зберігає результат для модуля, який завантажується безпосередньо з командного рядка. По-друге, він не перевіряє кеш, якщо немає вихідного модуля. Щоб підтримувати дистрибутив без вихідного коду (лише скомпільований), скомпільований модуль має бути у вихідному каталозі, а вихідного модуля не повинно бути.

Деякі поради експертам:

- Ви можете використовувати перемикачі `-O` або `-OO` у команді Python, щоб зменшити розмір скомпільованого модуля. Перемикач `-O` видаляє оператори assert, перемикач `-OO` видаляє як оператори assert, так і рядки __doc__. Оскільки деякі програми можуть покладатися на їх наявність, вам слід використовувати цей параметр, лише якщо ви знаєте, що робите. «Оптимізовані» модулі мають тег `opt-` і зазвичай менші. Майбутні випуски можуть змінити результати оптимізації.

- Програма не працює швидше, коли вона читається з файлу `.pyc`, ніж коли вона зчитується з файлу `.py`; єдине, що є швидшим у файлах `.pyc`, це швидкість, з якою вони завантажуються.

- Модуль `compileall` може створювати файли .pyc для всіх модулів у каталозі.

- Більш детальну інформацію про цей процес, включаючи блок-схему рішень, можна знайти в PEP 3147.

## 6.2. Стандартні модулі

Python постачається з бібліотекою стандартних модулів, описаних в окремому документі, Довідник бібліотеки Python (далі «Довідник бібліотеки»). Деякі модулі вбудовані в інтерпретатор; вони надають доступ до операцій, які не є частиною ядра мови, але, тим не менш, вбудовані, або для ефективності, або для забезпечення доступу до примітивів операційної системи, таких як системні виклики. Набір таких модулів є опцією конфігурації, яка також залежить від базової платформи. Наприклад, модуль `winreg` доступний лише в системах Windows. Один окремий модуль заслуговує на увагу: `sys`, який вбудовано в кожен інтерпретатор Python. Змінні `sys.ps1` і `sys.ps2` визначають рядки, які використовуються як первинні та додаткові підказки:

    >>> import sys
    >>> sys.ps1
    '>>> '
    >>> sys.ps2
    '... '
    >>> sys.ps1 = 'C> '
    C> print('Yuck!')
    Yuck!
    C>

Ці дві змінні визначені, лише якщо інтерпретатор перебуває в інтерактивному режимі.

Змінна `sys.path` - це список рядків, який визначає шлях пошуку модулів інтерпретатором. Він ініціалізується шляхом за замовчуванням, взятим із змінної середовища `PYTHONPATH`, або з вбудованого за замовчуванням, якщо `PYTHONPATH` не встановлено. Ви можете змінити його за допомогою стандартних операцій зі списком:

    >>> import sys
    >>> sys.path.append('/ufs/guido/lib/python')

## 6.3. Функція `dir()`

Вбудована функція `dir()` використовується, щоб дізнатися, які імена визначає модуль. Він повертає відсортований список рядків:

    >>> import fibo, sys
    >>> dir(fibo)
    ['__name__', 'fib', 'fib2']
    >>> dir(sys)
    ['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__',
     '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__',
     '__stderr__', '__stdin__', '__stdout__', '__unraisablehook__',
     '_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework',
     '_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook',
     'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix',
     'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing',
     'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info',
     'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info',
     'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth',
     'getallocatedblocks', 'getdefaultencoding', 'getdlopenflags',
     'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile',
     'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval',
     'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
     'intern', 'is_finalizing', 'last_traceback', 'last_type', 'last_value',
     'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
     'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'pycache_prefix',
     'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setdlopenflags',
     'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr',
     'stdin', 'stdout', 'thread_info', 'unraisablehook', 'version', 'version_info',
     'warnoptions']

Без аргументів `dir()` перераховує імена, які ви визначили на даний момент:

    >>> a = [1, 2, 3, 4, 5]
    >>> import fibo
    >>> fib = fibo.fib
    >>> dir()
    ['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']

Зверніть увагу, що в ньому перераховано всі типи імен: змінні, модулі, функції тощо.

`dir()` не містить списку вбудованих функцій і змінних. Якщо вам потрібен їх список, вони визначені в стандартному модулі `builtins`:

    >>> import builtins
    >>> dir(builtins)
    ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
     'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
     'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
     'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
     'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
     'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
     'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
     'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
     'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
     'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
     'NotImplementedError', 'OSError', 'OverflowError',
     'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
     'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
     'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
     'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
     'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
     'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
     'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
     '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
     'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
     'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
     'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
     'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
     'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
     'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
     'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
     'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
     'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
     'zip']

## 6.4. пакети

Packages are a way of structuring Python’s module namespace by using «dotted module names». For example, the module name `A.B` designates a submodule named `B` in a package named `A`. Just like the use of modules saves the authors of different modules from having to worry about each other’s global variable names, the use of dotted module names saves the authors of multi-module packages like NumPy or Pillow from having to worry about each other’s module names.

Припустімо, ви хочете розробити набір модулів («пакет») для однакової обробки звукових файлів і звукових даних. Існує багато різних форматів звукових файлів (зазвичай розпізнаються за їх розширенням, наприклад: `.wav`, `.aiff`, `.au`), тому вам може знадобитися створювати та підтримувати зростаюча колекція модулів для перетворення між різними форматами файлів. Існує також багато різних операцій, які ви можете виконати зі звуковими даними (наприклад, мікшування, додавання відлуння, застосування функції еквалайзера, створення штучного стереоефекту), тож на додаток ви будете писати нескінченний потік модулів для виконання ці операції. Ось можлива структура для вашого пакета (виражена в термінах ієрархічної файлової системи):

    sound/                          Top-level package
          __init__.py               Initialize the sound package
          formats/                  Subpackage for file format conversions
                  __init__.py
                  wavread.py
                  wavwrite.py
                  aiffread.py
                  aiffwrite.py
                  auread.py
                  auwrite.py
                  ...
          effects/                  Subpackage for sound effects
                  __init__.py
                  echo.py
                  surround.py
                  reverse.py
                  ...
          filters/                  Subpackage for filters
                  __init__.py
                  equalizer.py
                  vocoder.py
                  karaoke.py
                  ...

Під час імпортування пакета Python шукає підкаталог пакета в каталогах `sys.path`.

The `__init__.py` files are required to make Python treat directories containing the file as packages (unless using a namespace package, a relatively advanced feature). This prevents directories with a common name, such as `string`, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, `__init__.py` can just be an empty file, but it can also execute initialization code for the package or set the `__all__` variable, described later.

Користувачі пакету можуть імпортувати окремі модулі з пакета, наприклад:

    import sound.effects.echo

This loads the submodule `sound.effects.echo`. It must be referenced with its full name.

    sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

Альтернативний спосіб імпорту субмодуля:

    from sound.effects import echo

This also loads the submodule `echo`, and makes it available without its package prefix, so it can be used as follows:

    echo.echofilter(input, output, delay=0.7, atten=4)

Ще одним варіантом є імпорт потрібної функції або змінної безпосередньо:

    from sound.effects.echo import echofilter

Again, this loads the submodule `echo`, but this makes its function `echofilter()` directly available:

    echofilter(input, output, delay=0.7, atten=4)

Зауважте, що при використанні `з елемента імпорту пакета`, елемент може бути або підмодулем (або підпакетом) пакета, або іншим ім’ям, визначеним у пакеті, як-от функція, клас або змінна. Оператор `import` спочатку перевіряє, чи визначено елемент у пакеті; якщо ні, він припускає, що це модуль, і намагається його завантажити. Якщо не вдається знайти його, виникає виняток `ImportError`.

Навпаки, при використанні такого синтаксису, як `import item.subitem.subsubitem`, кожен елемент, крім останнього, має бути пакетом; останній елемент може бути модулем або пакетом, але не може бути класом, функцією чи змінною, визначеною в попередньому елементі.

### 6.4.1. Імпортування * з пакету

Тепер що відбувається, коли користувач пише `from sound.effects import *`? В ідеалі можна було б сподіватися, що це якимось чином переходить до файлової системи, знаходить, які підмодулі присутні в пакунку, і імпортує їх усі. Це може зайняти багато часу, а імпортування субмодулів може мати небажані побічні ефекти, які мають статися лише тоді, коли субмодуль імпортовано явно.

Єдине рішення полягає в тому, щоб автор пакета надав явний індекс пакета. Інструкція `import` використовує таку умову: якщо код `__init__.py` пакета визначає список під назвою `__all__`, він вважається списком імен модулів, які слід імпортувати, коли Зустрічається `from package import *`. Автор пакета повинен підтримувати цей список актуальним, коли виходить нова версія пакета. Автори пакетів також можуть вирішити не підтримувати його, якщо вони не бачать користі для імпортування * зі свого пакета. Наприклад, файл `sound/effects/__init__.py` може містити такий код:

    __all__ = ["echo", "surround", "reverse"]

This would mean that `from sound.effects import *` would import the three named submodules of the `sound.effects` package.

Be aware that submodules might become shadowed by locally defined names. For example, if you added a `reverse` function to the `sound/effects/__init__.py` file, the `from sound.effects import *` would only import the two submodules `echo` and `surround`, but not the `reverse` submodule, because it is shadowed by the locally defined `reverse` function:

    __all__ = [
        "echo",      # refers to the 'echo.py' file
        "surround",  # refers to the 'surround.py' file
        "reverse",   # !!! refers to the 'reverse' function now !!!
    ]

    def reverse(msg: str):  # <-- this name shadows the 'reverse.py' submodule
        return msg[::-1]    #     in the case of a 'from sound.effects import *'

If `__all__` is not defined, the statement `from sound.effects import *` does not import all submodules from the package `sound.effects` into the current namespace; it only ensures that the package `sound.effects` has been imported (possibly running any initialization code in `__init__.py`) and then imports whatever names are defined in the package. This includes any names defined (and submodules explicitly loaded) by `__init__.py`. It also includes any submodules of the package that were explicitly loaded by previous `import` statements. Consider this code:

    import sound.effects.echo
    import sound.effects.surround
    from sound.effects import *

In this example, the `echo` and `surround` modules are imported in the current namespace because they are defined in the `sound.effects` package when the `from...import` statement is executed. (This also works when `__all__` is defined.)

Хоча певні модулі призначені для експорту лише імен, які відповідають певним шаблонам, коли ви використовуєте `import *`, це все ще вважається поганою практикою у робочому коді.

Пам’ятайте, що немає нічого поганого у використанні `from package import specific_submodule`! Фактично, це рекомендована нотація, якщо тільки імпортуючому модулю не потрібно використовувати підмодулі з однаковими назвами з різних пакунків.

### 6.4.2. Внутрішньопакетні посилання

When packages are structured into subpackages (as with the `sound` package in the example), you can use absolute imports to refer to submodules of siblings packages. For example, if the module `sound.filters.vocoder` needs to use the `echo` module in the `sound.effects` package, it can use `from sound.effects import echo`.

You can also write relative imports, with the `from module import name` form of import statement. These imports use leading dots to indicate the current and parent packages involved in the relative import. From the `surround` module for example, you might use:

    from . import echo
    from .. import formats
    from ..filters import equalizer

Зауважте, що відносний імпорт базується на назві поточного модуля. Оскільки назва головного модуля завжди `"__main__"`, модулі, призначені для використання як головного модуля програми Python, повинні завжди використовувати абсолютний імпорт.

### 6.4.3. Пакунки в кількох каталогах

Packages support one more special attribute, `__path__`. This is initialized to be a sequence of strings containing the name of the directory holding the package’s `__init__.py` before the code in that file is executed. This variable can be modified; doing so affects future searches for modules and subpackages contained in the package.

Хоча ця функція не часто потрібна, її можна використовувати для розширення набору модулів, які містяться в пакеті.

Виноски

[1]

In fact function definitions are also „statements“ that are „executed“; the execution of a module-level function definition adds the function name to the module’s global namespace.