Spec-Zone.ru › Python 3.13

Модули

Если вы завершите работу интерпретатора Python и запустите его снова, созданные вами определения (функции и переменные) будут потеряны. Поэтому, если вы хотите написать довольно длинную программу, лучше подготовить вводные данные для интерпретатора с помощью текстового редактора и запустить его, передав этот файл в качестве входных данных. Это называется созданием скрипта. По мере увеличения программы вам может понадобиться разделить её на несколько файлов для удобства сопровождения. Возможно, вы также захотите использовать удобную функцию, написанную вами для нескольких программ, не копируя её определение в каждую программу.

Для этого в Python предусмотрен способ помещать определения в файл и использовать их в скрипте или в интерактивном экземпляре интерпретатора. Такой файл называется модулем; определения из модуля можно импортировать в другие модули или в модуль main (совокупность переменных, доступных в скрипте, запущенном на верхнем уровне, и в режиме калькулятора).

Модуль — это файл, содержащий определения и инструкции 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

Это не добавляет имена функций, определённых в fibo, непосредственно в текущее пространство имён (подробнее см. раздел Области видимости и пространства имён Python); туда добавляется только имя модуля fibo. С помощью имени модуля можно обращаться к функциям:

>>> 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] (Они также выполняются, если файл запущен как скрипт.)

У каждого модуля есть собственное пространство имён, которое используется в качестве глобального пространства имён всеми функциями, определёнными в модуле. Таким образом, автор модуля может использовать в нём глобальные переменные, не беспокоясь о случайных конфликтах с глобальными переменными пользователя. С другой стороны, если вы знаете, что делаете, то можете обращаться к глобальным переменным модуля с помощью той же записи, что используется для обращения к его функциям, modname.itemname.

Модули могут импортировать другие модули. Принято, хотя и не обязательно, размещать все инструкции import в начале модуля (или скрипта). Имена импортированных модулей, размещённые на верхнем уровне модуля (вне функций и классов), добавляются в глобальное пространство имён модуля.

Существует разновидность инструкции import, которая импортирует имена из модуля непосредственно в пространство имён импортирующего модуля. Например:

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

При этом имя модуля, из которого выполняется импорт, не добавляется в локальное пространство имён (поэтому в примере имя fibo не определено).

Есть даже вариант, который импортирует все имена, определённые в модуле:

>>> 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(), например import 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. Путь поиска модулей

При импорте модуля с именем spam интерпретатор сначала ищет встроенный модуль с таким именем. Имена этих модулей перечислены в sys.builtin_module_names. Если модуль не найден, интерпретатор ищет файл с именем spam.py в списке каталогов, заданном переменной sys.path. Переменная sys.path инициализируется с учётом следующих расположений:

  • Каталог, содержащий входной скрипт (или текущий каталог, если файл не указан).
  • PYTHONPATH (список имён каталогов с тем же синтаксисом, что и у переменной оболочки PATH).
  • Значение по умолчанию, зависящее от способа установки (по соглашению включает каталог site-packages, обработкой которого занимается модуль site).

Подробнее см. в разделе Инициализация пути поиска модулей sys.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. Пакеты

Пакеты позволяют структурировать пространство имён модулей Python с помощью «составных имён модулей», разделённых точками. Например, имя модуля A.B обозначает подмодуль B в пакете A. Подобно тому, как модули избавляют авторов разных модулей от необходимости беспокоиться о совпадении имён их глобальных переменных, составные имена модулей избавляют авторов многомодульных пакетов, таких как NumPy или Pillow, от необходимости беспокоиться о совпадении имён модулей.

Предположим, вы хотите разработать коллекцию модулей («пакет») для единообразной работы со звуковыми файлами и аудиоданными. Существует множество форматов звуковых файлов (обычно определяемых по расширению, например: .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 в поисках подкаталога пакета.

Файлы __init__.py необходимы, чтобы Python считал содержащие их каталоги пакетами (если только не используется пакет пространства имён — относительно продвинутая возможность). Это не позволяет каталогам с распространёнными именами, например string, случайно скрывать действительные модули, расположенные далее в пути поиска модулей. В простейшем случае файл __init__.py может быть пустым, но в нём также можно выполнять код инициализации пакета или задавать переменную __all__, о которой речь пойдёт далее.

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

import sound.effects.echo

Эта инструкция загружает подмодуль sound.effects.echo. На него нужно ссылаться по полному имени.

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

Другой способ импортировать подмодуль:

from sound.effects import echo

Эта инструкция также загружает подмодуль echo и делает его доступным без префикса пакета, поэтому его можно использовать так:

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

Ещё один вариант — напрямую импортировать нужную функцию или переменную:

from sound.effects.echo import echofilter

И в этом случае загружается подмодуль echo, но его функция echofilter() становится доступна напрямую:

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

Обратите внимание, что при использовании from package import item элементом может быть подмодуль (или подпакет) пакета либо другое имя, определённое в пакете, например функция, класс или переменная. Инструкция 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"]

Это означает, что инструкция from sound.effects import * импортирует три указанных подмодуля пакета sound.effects.

Имейте в виду, что подмодули могут быть затенены локально определёнными именами. Например, если добавить функцию reverse в файл sound/effects/__init__.py, инструкция from sound.effects import * импортирует только два подмодуля — echo и surround, — но не подмодуль reverse, поскольку его затеняет локально определённая функция reverse:

__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 *'

Если __all__ не определён, инструкция from sound.effects import * не импортирует все подмодули пакета sound.effects в текущее пространство имён; она только гарантирует, что пакет sound.effects импортирован (при этом, возможно, выполняется код инициализации из __init__.py), а затем импортирует все имена, определённые в пакете. Сюда входят имена, определённые (и подмодули, явно загруженные) файлом __init__.py. Сюда также входят все подмодули пакета, явно загруженные предыдущими инструкциями import. Рассмотрим этот код:

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

В этом примере модули echo и surround импортируются в текущее пространство имён, поскольку на момент выполнения инструкции from...import они определены в пакете sound.effects. (Это работает и в том случае, если определён __all__.)

Некоторые модули при использовании import * специально экспортируют только имена, соответствующие определённым шаблонам, но в рабочем коде такая практика всё равно считается плохой.

Помните: использовать from package import specific_submodule вполне допустимо! На самом деле это рекомендуемый способ записи, если только импортирующему модулю не требуется использовать подмодули с одинаковыми именами из разных пакетов.

6.4.2. Внутрипакетные ссылки

Если пакеты организованы во вложенные пакеты (как пакет sound в примере), для обращения к подмодулям соседних пакетов можно использовать абсолютный импорт. Например, если модулю sound.filters.vocoder требуется использовать модуль echo из пакета sound.effects, можно написать from sound.effects import echo.

Можно также использовать относительный импорт с формой инструкции from module import name. В таких инструкциях начальные точки обозначают текущий и родительские пакеты, участвующие в относительном импорте. Например, из модуля surround можно написать:

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

Обратите внимание, что относительный импорт основывается на имени пакета текущего модуля. Поскольку у главного модуля нет пакета, модули, предназначенные для использования в качестве главного модуля приложения Python, всегда должны использовать абсолютный импорт.

6.4.3. Пакеты в нескольких каталогах

У пакетов есть ещё один специальный атрибут — __path__. Изначально ему присваивается последовательность строк с именами каталогов, содержащих файл __init__.py пакета; это происходит до выполнения кода в этом файле. Эту переменную можно изменять; такие изменения влияют на последующий поиск модулей и подпакетов, содержащихся в пакете.

Хотя эта возможность требуется нечасто, с её помощью можно расширить набор модулей, найденных в пакете.

Сноски

[1]

На самом деле определения функций тоже являются «инструкциями», которые «выполняются»: выполнение определения функции на уровне модуля добавляет имя функции в глобальное пространство имён модуля.

© 2001–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/tutorial/modules.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API