Модули
Если выйти из интерпретатора 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
Это не добавляет имена функций, определённых в 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удаляет утверждения, переключатель-OOудаляет как утверждения, так и строки __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 использует следующую конвенцию: если код пакета определяет список с именем __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 импортируются в текущем пространстве имён, потому что они определены в пакете sound.effects во время выполнения оператора from...import. (Это также работает, когда __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
Обратите внимание, что относительные импорты основаны на имени текущего модуля. Поскольку имя основного модуля всегда "__main__", модули, предназначенные для использования в качестве основного модуля приложения Python, должны всегда использовать абсолютные импорты.
6.4.3. Пакеты в нескольких каталогах
Пакеты поддерживают ещё одну специальную атрибут, __path__. Он инициализируется списком, содержащим имя каталога, содержащего __init__.py пакета до выполнения кода в этом файле. Эта переменная может быть изменена; это повлияет на будущие поиски модулей и подпакетов, содержащихся в пакете.
Хотя эта функция не часто нужна, её можно использовать для расширения набора модулей, найденных в пакете.
Примечания
© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/tutorial/modules.html