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

При этом имена функций, определенных в fibo, не добавляются непосредственно к текущему namespace (более подробную информацию смотрите в Области и пространства имен 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`Это часто :data:`sys.builtin_module_names используется spam.py либо sys.path для sys.path обеспечения удобного пользовательского интерфейса модуля, либо в целях тестирования (при запуске модуля в виде сценария выполняется набор тестов).

  • Это часто используется либо для обеспечения удобного пользовательского интерфейса модуля, либо в целях тестирования (при запуске модуля в виде сценария выполняется набор тестов).

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

  • site-packages (список имен каталогов с тем же синтаксисом, что и у переменной оболочки site).

Инициализация пути поиска модуля sys.path (список имен каталогов с тем же синтаксисом, что и у переменной оболочки ).

Примечание

On file systems which support symlinks, the directory containing the input script is calculated after the symlink is followed. In other words the directory containing the symlink is not added to the module search path.

sys.path (список имен каталогов с тем же синтаксисом, что и у переменной оболочки Стандартные модули).

6.1.3. (список имен каталогов с тем же синтаксисом, что и у переменной оболочки ).

__pycache__ (список имен каталогов с тем же синтаксисом, что и у переменной оболочки module.version.pyc) __pycache__/spam.cpython-33.pyc .

Python checks the modification date of the source against the compiled version to see if it’s out of date and needs to be recompiled. This is a completely automatic process. Also, the compiled modules are platform-independent, so the same library can be shared among systems with different architectures.

Python does not check the cache in two circumstances. First, it always recompiles and does not store the result for the module that’s loaded directly from the command line. Second, it does not check the cache if there is no source module. To support a non-source (compiled only) distribution, the compiled module must be in the source directory, and there must not be a source module.

Несколько советов для экспертов:

  • -O`Несколько :option:-OO` советов -O для -OO экспертов opt- :

  • .pyc``Несколько ``.py советов .pyc для экспертов:

  • :mod:`compileall`Несколько советов для экспертов:

  • :pep:`3147`Несколько советов для экспертов:

6.2. Стандартные модули

winreg`Стандартные :mod:`sys модул 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. Пакеты

A.B`Пакет ``B` A ы

.wav`Пакет :file:.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 рассматривать каталоги, содержащие файл, как пакеты (если только не используется namespace package, относительно продвинутая функция). Это предотвращает непреднамеренное сокрытие каталогами с общим именем, такими как string, допустимых модулей, которые встречаются позже в пути поиска модуля. В простейшем случае __init__.py может быть просто пустым файлом, но он также может выполнять код инициализации пакета или устанавливать переменную __all__, описанную ниже.

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

import sound.effects.echo

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

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

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

from sound.effects import echo

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

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

Еще одним вариантом является прямой импорт нужной функции или переменной:

from sound.effects.echo import echofilter

echo`Еще одним :func:!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 импортируются в текущее пространство имен, поскольку они определены в пакете 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 пакета, перед выполнением кода в этом файле. Эта переменная может быть изменена; это повлияет на будущий поиск модулей и подпакетов, содержащихся в пакете.

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

Сноски

Вернуться на верх