Документация Python неофициальный перевод
Содержание страницы

6. МодулиModules

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

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

Модуль – это файл, содержащий определения и инструкции Python. Имя файла – это имя модуля с добавленным суффиксом .py. Внутри модуля имя модуля (в виде строки) доступно как значение глобальной переменной __name__. Например, с помощью любимого текстового редактора создайте файл с именем fibo.py в текущем каталоге со следующим содержимым:

# Модуль чисел Фибоначчи

def fib(n):    # вывести ряд Фибоначчи до n
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

def fib2(n):   # возвращает ряд Фибоначчи до 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. Подробнее о модуляхMore on Modules

Модуль может содержать исполняемые инструкции, а также определения функций. Эти инструкции предназначены для инициализации модуля. Они выполняются только при первом обнаружении имени модуля в инструкции импорта. 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. Выполнение модулей как скриптовExecuting modules as scripts

Когда вы запускаете модуль 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. Путь поиска модулейThe Module Search Path

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

  • Каталог, содержащий входной скрипт (или текущий каталог, если файл не указан).

  • PYTHONPATH (список имён каталогов с тем же синтаксисом, что и переменная оболочки PATH).

  • Зависящее от установки значение по умолчанию (по соглашению включающее каталог site-packages, обрабатываемый модулем site).

Примечание

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

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

6.1.3. «Скомпилированные» файлы Python“Compiled” Python files

Чтобы ускорить загрузку модулей, 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. Стандартные модулиStandard Modules

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()The dir() Function

Встроенная функция 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

Пакеты – это способ структурирования пространства имён модулей 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. Импорт * из пакетаImporting * From a Package

Что происходит, когда пользователь пишет 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.

Если __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 импортируются в текущее пространство имён, потому что они определены в пакете sound.effects при выполнении инструкции from...import. (Это также работает, когда определён __all__.)

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

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

6.4.2. Ссылки внутри пакетаIntra-package References

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

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

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

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

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

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

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

Сноски

1

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