Модули в Питоне.

Работая в интерактивном режиме интерпретатора, вы, наверное, решили, что писать большие программы в Питоне невозможно, так как после выхода из интерпретатора определения ваших функций “исчезают” бесследно. А хотелось бы иметь возможность написать несколько функций в одном файле и потом иметь возможность обращаться к ним из других программ(принцип повторного использования кода). Такая возможность в Питоне существует. Это технология модулей, то есть текстовых файлов, содержащих в себе какой-либо набор функций(желательно объединённых по какому-либо признаку). Большинство функций стандартной библиотеки Питона реализовано именно в модулях. Создать модуль очень просто: просто зайдите в свой любимый текстовый редактор, напишите определения своих функций с помощью ключевого слова def, не забывайте также об отступах, которые выделяют блоки в программе. Ставить символы >>> и .... в текстовом редакторе нельзя, так как это вызовет синтаксическую ошибку. Модули Питона имеют расширение .py и могут содержать только текст. Внутри модуля существует глобальная переменная __name__, в которой содержится имя текущего модуля. Напрмер, создайте файл с именем fibo.py, содержащим следующий код:

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

def fib(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 имя_модуля:

>>> import 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

Дополнительная информация о модулях.

Модули могут содержать в себе кроме определений функций и некоторый исполняемый код. Этот код не входит ни в какую функцию и исполняется интерпретатором, когда данный модуль подключается ключевым словом import. В исполняемом коде модуля можно использовать любые переменные, которые внутри модуля объявляются глобальными. Но каждый модуль имеет собственную таблицу переменных, так что случайное изменение таких переменных вне модуля исключено. Такой механизм обеспечивает стабильность работы модуля и соответствует принципу сокрытия информации.

Модули могут импортировать другие модули. Желательно, чтобы операторы 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

Информация о поиске модулей.

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

Компиляция скриптов на Питоне.

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

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

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

В модулях содержатся некоторые функции, позволяющие настраивать интерпретатор. Это в основном функции и переменные модуля sys. Например, переменные sys.ps1 и sys.ps2 хранят в себе приглашение интерпретатора:

>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = '[Python@localhost]# '
[Python@localhost]# print 'Ой!'
Ой!
[Python@localhost]#

Список sys.path хранит в себе пути поиска библиотек интерпретатором:

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

Встроенная функция dir([имя_модуля]) позволяет вывести все загруженные модули, может также вывести все объекты какого-либо конкретного модуля(с указанием имени модуля, в качестве аргумента dir()):

>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__',
 '__stdin__', '__stdout__', '_getframe', 'argv', 'builtin_module_names',
 'byteorder', 'copyright', 'displayhook', 'exc_info', 'exc_type',
 'excepthook', 'exec_prefix', 'executable', 'exit', 'getdefaultencoding',
 'getdlopenflags', 'getrecursionlimit', 'getrefcount', 'hexversion',
 'maxint', 'maxunicode', 'modules', 'path', 'platform', 'prefix', 'ps1',
 'ps2', 'setcheckinterval', 'setdlopenflags', 'setprofile',
 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'version',
 'version_info', 'warnoptions']

Встроенные функции Питона содержатся в модуле __builtin__(импортировать его для использования функций не нужно):

>>> import __builtin__
>>> dir(__builtin__)
['ArithmeticError', 'AssertionError', 'AttributeError',
 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
 'Exception', 'FloatingPointError', 'IOError', 'ImportError',
 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt',
 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
 'NotImplementedError', 'OSError', 'OverflowError', 'OverflowWarning',
 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError',
 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
 'SystemExit', 'TabError', 'TypeError', 'UnboundLocalError',
 'UnicodeError', 'UserWarning', 'ValueError', 'Warning',
 'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__',
 '__name__', 'abs', 'apply', 'buffer', 'callable', 'chr', 'classmethod',
 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr',
 'dict', 'dir', 'divmod', 'eval', 'execfile', 'exit', 'file', 'filter',
 'float', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id',
 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len',
 'license', 'list', 'locals', 'long', 'map', 'max', 'min', 'object',
 'oct', 'open', 'ord', 'pow', 'property', 'quit', 'range', 'raw_input',
 'reduce', 'reload', 'repr', 'round', 'setattr', 'slice', 'staticmethod',
 'str', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange',
 'zip']

Пакеты.

Несколько модулей в Питоне могут быть объединены по функциональному или какому-нибудь другому признаку. Для этого используются пакеты. Суть пакетов такова: вы объединяете несколько модулей по некому признаку в пакет, затем могут появиться другие пакеты с модулями, организовать структуру пакетов можно по принципу дерева. Принципу дерева подчиняются также папки в файловых системах. То есть пакеты подобны папкам на диске:

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 нужен интерпретатору для того, чтобы расценивать каталог на диске, как пакет. Данный файл может быть пустым, но может содержать исполняемый код, для инициализации переменной __all__.

Из пакетов можно импортировать отдельные модули несколькими путями:

1. import Sound.Effects.echo 

Загрузка модуля echo. Далее должно указываться полное имя модуля.:

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


2. from Sound.Effects import echo

Также загрузка модуля echo, но теперь к нему можно обращаться без указания имени модуля:

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


3. from Sound.Effects.echo import echofilter

Прямой импорт объекта из пакета. Теперь вы можете обращаться к функции echofilter() непосредственно через её имя:

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

Из пакетов можно также импортировать все модули. Но трюк с import * не пройдёт на некоторых операционных системах(DOS, Windows, MAC), так как в них не различается регистр у файлов и папок, а так как в Питоне регистр различается, то это может привести к непредсказуемым именам модулей(Echo, echo, ECHO, eChO). Поэтому для надёжности лучше создавать список модулей пакета в файле __init__.py. Для этого присвойте переменной __all__ список всех имён модулей(строковый тип элемента списка). Такой подход обеспечит корректную интерпретацию пакета на любой системе.

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

А в самом коде можно теперь применять import *:

from Sound.Effects import *

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

Назад | Содержание | Вперед