Информационные технологииStfw.Ru 🔍

Модули

Python позволяет поместить определения в файл и использовать их в программах и интерактивном режиме. Такой файл называется модулем. Определения из модуля могут быть импортированы в другие модули и в главный модуль.
🕛 11.07.2009, 13:56
Создание и использование модулей

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

'''\
Генерация и вывод чисел Фибоначчи
'''
def fib(n): '''Выводит последовательность чисел Фибоначчи, не превышающих n''' a, b = 0, 1 while b < n: print b, a, b = b, a+b

def fib2(n): '''Возвращает список, содержащий числа ряда Фибоначчи, не превышающие n''' result = [] a, b = 0, 1 while b < n: result.append(b) a, b = b, a+b return result

Теперь запустите интерпретатор и импортируйте только что созданный модуль:

>>> import fibo

Эта инструкция не вводит имена функций, определенных в fibo прямо в текущее пространство имен, она только вводит имя модуля fibo. Используя имя модуля, Вы можете получить доступ к функциям:

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

Если Вы собираетесь использовать функцию часто, можете присвоить ее локальной переменной:

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

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

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

Модули могут импортировать другие модули. Обычно инструкцию import располагают в начале модуля или программы. Имена импортируемых модулей помещаются в текущее пространство имен импортирующего модуля или программы.

Другой вариант инструкции import импортирует имена из модуля непосредственно в текущее пространство имен:

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

В этом случае имя модуля не будет представлено в текущей области видимости (в приведенном примере, имя fibo не определено).

Еще один вариант инструкции import позволяет импортировать все имена, определенные в модуле, кроме имен, начинающихся с символа подчеркивания ('_'):

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

Часто возникает необходимость импортировать модуль или объект модуля, используя для него локальное имя, отличное от исходного. Например, следующий код позволяет заменить имя string на _string (которое не будет импортироваться инструкцией 'from my_module import *') при написании модуля:

import string
_string = string
del string

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

import anydbm
dbopen = anydbm.open

Начиная с версии 2.0, подобные операции можно произвести гораздо проще (и безопаснее) благодаря расширению синтаксиса инструкции import:

import string as _string
from anydbm import open as dbopen

Следует заметить, что as не является зарезервированным словом, и Вы можете попрежнему определять переменные с таким именем.

Если имя модуля, который необходимо импортировать, становится известным только во время выполнения программы, Вы можете воспользоваться инструкцией exec ('exec 'import ' + module_name') или встроенной функцией _import_() (см. раздел 12).

Поиск модулей

Когда импортируется модуль, например spam, интерпретатор ищет файл с именем 'spam.py' в текущем каталоге, затем в каталогах, указанных в переменной окружения PYTHONPATH, затем в зависящих от платформы путях по умолчанию.

Каталоги, в которых осуществляется поиск, хранятся в переменной sys.path. Таким образом, программы на языке Python могут изменять пути поиска модулей во время их выполнения.

"Компилированные" файлы

Для ускорения запуска программ, использующих большое количество модулей, если уже существует файл с именем 'spam.pyc' в том же каталоге, где найден 'spam.py', считается, что он содержит "байт-компилированный" модуль spam. Если такого файла нет, то он создается, и время последнего изменения 'spam.py' записывается в созданном 'spam.pyc' (при последующем использовании, '.pyc'-файл игнорируется, если исходный '.py'-файл был изменен).

Обычно Вам не надо ничего делать для создания 'spam.pyc'. Как только 'spam.py' успешно откомпилирован, интерпретатор пытается записать компилированную версию в 'spam.pyc'. Если интерпретатору по каким-либо причинам это не удается (например, недостаточно пользовательских полномочий), ошибки не возникает. Если же файл записан не полностью, далее он распознается как неработоспособный и игнорируется. Содержимое байт-компилированных файлов является платформно-независимым (но может быть разным для разных версий интерпретатора), так что каталог с модулями может совместно использоваться машинами с разными архитектурами.

Несколько тонкостей для опытных пользователей:
* Если интерпретатор вызывается с опцией -O или переменная окружения PYTHONOPTIMIZE имеет непустое значение, интерпретатор генерирует оптимизированный байт-код и сохраняет его в '.pyo'-файлах. В настоящий момент оптимизация дает не слишком много: при этом удаляются инструкции assert, игнорируются инструкции 'if _debug_: ... ', не сохраняется информация о нумерации строк в исходных '.py'-файлах. В этом случае оптимизируются все используемые модули, '.pyc'-файлы игнорируются. * Опция -OO приводит к тому, что интерпретатор выполняет оптимизацию которая, в некоторых (редких) случаях, может привести к сбоям в работе программ. В настоящий момент, помимо действий, выполняемых с опцией -O, удаляются строки документации, давая более компактные '.pyo'-файлы. Так как некоторые программы могут рассчитывать на наличие строк документации, используйте эту опцию с осторожностью. * Для программы, запускаемой из командной строки, байт-код никогда не записывается в '.pyc'- или '.pyo'-файл. Поэтому, если Вы хотите уменьшить время, требующееся для загрузки, поместите большую часть кода в модуль, оставив в программе лишь загрузочную часть, которая импортирует этот модуль. * Возможно использование модуля (или запуск программы) при наличии '.pyc'-файла (или '.pyo'-файла, если используется одна из опций -O или -OO), даже если отсутствует '.py'-файл. Таким образом, Вы можете распространять библиотеки и программы в виде, из которого относительно сложно извлечь информацию об используемых алгоритмах. * Модуль compileall позволяет создать '.pyc'- (или '.pyo'-) файлы для всех модулей в каталоге. Это может быть особенно полезно, если вы хотите ограничить доступ к каталогу, в котором находится библиотека. Заметим, что интерпретатор не будет использовать '.pyc'-файлы, если он запущен с включенной оптимизацией, и '.pyo'-файлы, если оптимизация выключена (если же отсутствует '.py'-файл, модуль окажется недоступным).

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

Python распространяется с библиотекой стандартных модулей, которой посвящена третья часть книги. Часть модулей встроена в интерпретатор, обеспечивая доступ к операциям, которые не входят в ядро языка, но, тем не менее, встроены либо из соображений эффективности, либо для обеспечения доступа к примитивам операционной системы.Набор таких модулей зависит от конфигурации, так, например, модуль amoeba присутствует только в системах, которые поддерживают примитивы Amoeba. Один модуль заслуживает особого внимания: sys, который присутствует всегда. Переменные sys.ps1 и sys.ps2 при работе в интерактивном режиме определяют строки, используемые для первичного и вторичного приглашения:

>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print 'Привет!'
Привет!
C>

Переменная sys.path содержит список строк с именами каталогов, в которых происходит поиск модулей. Она инициализируется из значения переменной окружения PYTHONPATH и встроенного значения по умолчанию. Вы можете изменить ее значение, используя стандартные операции со списками:

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

Функция dir()

Для выяснения имен, определенных в модуле, можно использовать встроенную функцию dir(). Она возвращает отсортированный список строк:

>>> import fibo, sys
>>> dir(fibo)
['_name_', 'fib', 'fib2']
>>> dir(sys)
['_name_', 'argv', 'builtin_module_names',
'copyright', 'exit', 'maxint', 'modules', 'path',
'ps1', 'ps2', 'setprofile', 'settrace', 'stderr',
'stdin', 'stdout', 'version']

Без аргументов, dir() возвращает список имен, определенных в текущей области видимости:

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

Обратите внимание, что перечисляются имена объектов всех типов: переменные, модули, функции и т. д.

Список, возвращаемый функцией dir() не содержит имена встроенных функций и переменных - они определены в стандартном модуле _builtin_:

>>> import _builtin_
>>> dir(_builtin_)
['AccessError', 'AttributeError', 'ConflictError',
'EOFError', 'IOError', 'ImportError', 'IndexError',
'KeyError', 'KeyboardInterrupt', 'MemoryError',
'NameError', 'None', 'OverflowError', 'RuntimeError',
'SyntaxError', 'SystemError', 'SystemExit',
'TypeError', 'ValueError', 'ZeroDivisionError',
'_name_', 'abs', 'apply', 'chr', 'cmp', 'coerce',
'compile', 'dir', 'divmod', 'eval', 'execfile',
'filter', 'float', 'getattr', 'hasattr', 'hash', 'hex',
'id', 'input', 'int', 'len', 'long', 'map', 'max',
'min', 'oct', 'open', 'ord', 'pow', 'range',
'raw_input', 'reduce', 'reload', 'repr', 'round',
'setattr', 'str', 'type', 'xrange']


Пакеты

Пакеты - способ структурирования пространств имен модулей, используя "точечную запись". Например, имя модуля A.B обозначает подмодуль с именем A в пакете B. Так же, как использование модулей делает безопасным использование глобального пространства имен авторами различных модулей, использование точечной записи делает безопасным использование имен модулей авторами многомодульных пакетов.

Предположим, Вы хотите спроектировать совокупность модулей ("пакет") для единообразной обработки звуковых файлов и данных. Существует множество форматов звуковых файлов (обычно распознаваемых по их расширению, например '.wav', '.aiff', '.au'), так что Вам необходимо создавать и поддерживать все возрастающий набор модулей для преобразования между различными форматами файлов. Вы можете захотеть выполнять множество различных операций над звуковыми данными (микширование, добавление эха, частотная обработка, создание искусственного стереоэффекта), то есть, вдобавок, Вы будете писать нескончаемый поток модулей для выполнения этих операций. Вот примерная структура Вашего пакета (выраженная в терминах иерархической файловой системы):

Sound/ Верхний уровень пакета _init_.py Инициализация пакета Formats/ Работа с файлами _init_.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py ... Effects/ Звуковые эффекты _init_.py echo.py surround.py reverse.py ... Filters/ Фильтры _init_.py equalizer.py vocoder.py karaoke.py ...

Файл '_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

В этом случае также загружается модуль Sound.Effects.echo, и делает его доступным для использования без префикса:

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

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

from Sound.Effects.echo import echofilter

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

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

Заметим, что при использовании 'from package import item', item может быть модулем, подпакетом или другим именем, определенном в пакете package, таким как функция, класс или переменная. Инструкция import сначала проверяет, определено ли имя item в пакете, если нет, считает его модулем и пытается загрузить. Если при загрузке возникает ошибка, генерируется исключение ImportError.

И наоборот, при использовании инструкции 'import item.subitem.subsubitem', каждая единица, кроме последней, должна быть пакетом. Последняя единица может быть модулем или пакетом, но не может быть классом, функцией или переменной, определенной в предыдущей единице.

Импортирование всего содержимого пакета (модуля)

Что же происходит, когда пользователь использует 'from Sound.Effects import *'? В идеале, интерпретатор должен каким-либо образом обойти файлы, находящиеся в каталоге пакета, и импортировать их все. К сожалению, такой подход не будет работать достаточно хорошо на таких платформах, как Macintosh и Windows, где файловая система не всегда имеет точную информацию о регистре букв в именах файлов. В этом случае нет надежного пути узнать, с каким именем должен быть импортирован файл с именем 'ECHO.PY': echo, Echo или ECHO.

Единственный выход для автора - снабдить пакет явным указателем его содержимого. Инструкция import использует следующее соглашение: если в инициализационном файле '_init_.py' определен список с именем _all_, он используется в качестве списка имен модулей, которые должны импортироваться при использовании 'from package import *'. Поддержка этого списка в соответствии с текущим составом пакета возлагается на автора. Можно также не определять список _all_, если авторы не считают уместным импортирование *. Например, файл 'Sounds/Effects/_init_.py' может содержать следующий код:

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

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

Если список _all_ не определен, 'from Sound.Effects import *' не будет импортировать все модули пакета Sound.Effects, а только имена, явным образом определенные в инициализационном файле '_init_.py' (включая явно импортированные в нем модули). Кроме того, в текущую область видимости попадут модули пакета, явно загруженные предыдущими инструкциями import, например:

import Sound.Effects.echo
import Sound.Effects.surround
from Sound.Effects import *

В приведенном примере, модули echo и surround импортируются в текущее пространство имен, потому что они уже определены в пакете Sound.Effects на момент выполнения инструкции from ... import.

Заметим, что импортирование всех имен, определенных в модуле или пакете, обычно приводит к засорению пространства имен и, как результат, к возможным конфликтам. (Некоторые модули специально спроектированы таким образом, чтобы экспортировать только имена, следующие определенному шаблону.) Кроме того, при этом глобальные переменные модуля становятся доступными только для чтения - при попытке присвоить такой переменной новое значение Вы создадите новую (локальную) переменную с таким же именем. А все изменения, внесенные в глобальные переменные модуля после его инициализации, не будут видны за его пределами.

Мы рекомендуем стараться использовать запись 'from package import specific_module', за исключением случаев, когда необходимо использовать модули с одинаковыми именами из разных пакетов.

Связи между модулями пакета

Часто возникает необходимость в связях между модулями одного пакета. Например, модуль surround может использовать модуль echo. В самом деле, подобные связи распространены настолько, что инструкция import сначала просматривает содержимое пакета, в который входит содержащий эту инструкцию модуль, и только потом в путях поиска модулей. Таким образом, модуль surround может просто использовать 'import echo' или 'from echo import echofilter'.

Когда пакеты разделены на подпакеты (пакет Sound в примере), нет краткой записи для ссылок между ответвлениями пакета - нужно использовать полное имя. Например, если модуль Sound.Filters.vocoder должен использовать модуль echo пакета Sound.Effects, нужно использовать 'from Sound.Effects import echo'.

Python   Теги:

Читать IT-новости в Telegram
Информационные технологии
Мы в соцсетях ✉