Python Tutorial 3
6. Модули
Можно работать в среде интерпретатора , а можно написать отдельный скрипт .
Если программа большая , она может состоять из нескольких скриптов .
Можно написать отдельную функцию , которая будет использоваться
множеством других программ .
Это можно реализовать с помощью модулей .
Набор переменных и методов одного модуля может быть импортирован
в другой модуль .
Имя файла совпадает с именем модуля .
Создадим модуль fibo.py :
# Fibonacci numbers module
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while b < n:
print b,
a, b = b, a+b
def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
return result
Теперь запустим его из-под интерпретатора :
Теперь у нас есть доступ к его функциям :
>>> 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
Модуль может импортировать другой модуль :
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
Другой вариант :
>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
Будут импортированы все имена .
6.1.1 Путь
При импорте модуля интерпретатор ищет скрипт в текущей директории .
После чего просматривается список директорий , определенный в переменной PYTHONPATH , которая имеет
такой же вид , как и системная переменная PATH. После чего поиск может быть продолжен в
/usr/local/lib/python.
Файл с расширением spam.pyc представляет из себя``byte-compiled'' версию исходника.
Содержание откомпилированной версии платформенно-независимое и может использоваться
на различных платформах .
- Опция интерпретатора -O генерит файл с расширением .pyo . Получается оптимизированный байт-код .
- Опция интерпретатора (-OO) создаст более оптимизированный код .
- Откомпилированные версии не выполняются быстрее самих исходников , они просто быстрее загружаются
- Для уменьшеня времени загрузки скрипта нужно использовать модули .
При этом тело самого скрипта может быть небольшим , а функции вызываться из модуля .
- Компиляция позволяет создавать дистрибутивные библиотеки для сторонних пользователей .
- Модуль compileall позволяет создавать .pyc файлы или
.pyo файлы с использованием опции -O для всего каталога .
6.2 Стандартные модули
В питоне есть библиотека стандартных модулей . Некоторые модули встроены в интерпретатор.
Например модуль sys встроен в каждый интерпретатор .
Переменные sys.ps1 , sys.ps2 используются в prompts вашего интерпретатора в интерактивном режиме :
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print 'Yuck!'
Yuck!
C>
Переменная sys.path берется из системной переменной
PYTHONPATH, ее можно модифицировать :
>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')
6.3 Функция dir()
Встроенная функция dir() используется для вывода всех идентификаторов модуля :
>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__',
'__stdin__', '__stdout__', '_getframe', 'api_version', 'argv',
'builtin_module_names', 'byteorder', 'callstats', 'copyright',
'displayhook', 'exc_clear', 'exc_info', 'exc_type', 'excepthook',
'exec_prefix', 'executable', 'exit', 'getdefaultencoding', 'getdlopenflags',
'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode',
'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache',
'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags',
'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout',
'version', 'version_info', 'warnoptions']
Без аргументов эта функция dir() выдает список текущих идентификаторов :
>>> a = [1, 2, 3, 4, 5]
>>> import fibo, sys
>>> fib = fibo.fib
>>> dir()
['__name__', 'a', 'fib', 'fibo', 'sys']
Для вывода списка встроенных имен-функций нужно использовать модуль __builtin__ :
>>> import __builtin__
>>> dir(__builtin__)
['ArithmeticError', 'AssertionError', 'AttributeError',
'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
'Exception', 'False', 'FloatingPointError', 'IOError', 'ImportError',
'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt',
'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
'NotImplementedError', 'OSError', 'OverflowError', 'OverflowWarning',
'PendingDeprecationWarning', 'ReferenceError',
'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration',
'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError',
'True', 'TypeError', 'UnboundLocalError', 'UnicodeError', 'UserWarning',
'ValueError', 'Warning', 'ZeroDivisionError', '__debug__', '__doc__',
'__import__', '__name__', 'abs', 'apply', 'bool', 'buffer',
'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex',
'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod',
'enumerate', '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', 'string', 'sum', 'super',
'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
6.4 Пакеты
Пакеты - это способ структуризации набора модулей в единый namespace
с использованием технологии ``dotted module names''.
Например A.B - модуль с именем "B" входит в пакет с именем
"A". Единый namespace избавляет автора от заботы по поводу глобальных переменных .
Предположим , нужно разработать пакет для управления м-пегами .
Существует множество музыкальных форматов -
.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
...
При импорте пакета питон будет искать его каталог в переменной sys.path .
Файлы , имеющие формат __init__.py необходимы для определения
входящих подкаталогов .
__init__.py может быть просто пустым файлом ,
но также может выполнять инициализирующий код или устанавливать переменные .
С помощью следующего префикса из пакета можно импортировать отдельные модули :
import Sound.Effects.echo
Вызов :
Sound.Effects.echo.echofilter(input, output, delay=0.7, atten=4)
Альтернативный путь импортирования модулей :
from Sound.Effects import echo
И его вызов :
echo.echofilter(input, output, delay=0.7, atten=4)
Еще один вариант импортирования напрямую :
from Sound.Effects.echo import echofilter
И вызов echofilter() :
echofilter(input, output, delay=0.7, atten=4)
6.4.1 Импорт с префиксом *
Что произойдет , если вызвать from Sound.Effects import
* ?
Нет никакой гарантии , что это будет работать на MAC или Windows - платформах ,
поскольку в них регистр имени модуля не различается , что подчас имеет значение .
Необходимо , чтобы в файле __init__.py был определен список __all__ ,
который включает в себя список модулей , обязательных при импортировании с префиксом frompackage import * .
Например , файл Sounds/Effects/__init__.py может включать следующий код :
__all__ = ["echo", "surround", "reverse"]
Это означает , что команда from Sound.Effects import * импортирует 3 модуля в пакете Sound .
Если __all__ не определено , команда from Sound.Effects
import * не будет импортировать все модули из каталога Sound.Effects; будут импортированы лишь те имена , которые определены явно в __init__.py или в самом пакете . Рассмотрим код :
import Sound.Effects.echo
import Sound.Effects.surround
from Sound.Effects import *
Здесь первые 2 модуля импортируются явно .
Вообще , префикс типа from Package import specific_submodule надежен в том смысле ,
что не будет конфликтов при импорте модулей с одинаковыми названиями из разных модулей .
Модули часто ссылаются друг на друга .
Например , surround может использовать echo .
Модуль surround может просто использовать import echo или
from echo import echofilter . Если модуль не найден в текущем пакете ,
поиск будет продолжен на уровень выше .
Когда пакеты структурированы в подпакеты (Sound),другие модули из этого-же пакета должны вызываться с полным путем , например если модуль Sound.Filters.vocoder вызывает echo модуль из Sound.Effects , нужно писать from
Sound.Effects import echo .
Пакеты поддерживают еще один атрибут - __path__.
В него входи имя каталога , в котором лежит головной __init__.py ,
и код которого выполняется в первую очередь .
|