Загальні зауваження
Якщо ви залишите інтерпретатор Пітона, а потім увійдете в нього знову, усі зроблені вами визначення функцій та змінних буде втрачено. Тому, якщо ви хочете написати дещо довшу програму, то для цього краще використовувати текстовий редактор і виконати програму, записану у файлі. Це зветься створенням скрипта. Коли програма збільшується, то ви можливо захочете розбити її на кілька файлів, щоб полегшити її утримування. Можливо, ви маєте кілька зручних функцій, що ви створили у різних програмах, і ви хочете їх використати без копіювання їхніх визначень у різні програми.
Щоб підтримати це, Пітон має певний механізм для створення визначень у файлі, які згодом можуть використовуватися у скрипті чи у діалоговому режимі інтерпретатора. Такий файл зветься модулем. Визначення, задані в модулі, імпортуються в інші модулі або в основний (main) модуль, який являє собою сукупність змінних, до яких ви маєте доступ у скрипті, що виконується на найвищому рівні в режимі калькулятора.
Модуль - це файл,
що складається
з визначень
та тверджень
Пітона. Назва
файла є назвою
модуля, до якої
додається
суфікс .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.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
, що напряму
імпортує назви
модуля у символьну
таблицю імпортуючого
модуля. Наприклад:
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
Ця операція
не додає до
локальної
символьної
таблиці назву
самого модуля,
з якого відбувся
імпорт (зокрема,
у цьому прикладі
назва fibo
- невизначена).
Існує також можливість для імпорту всіх назв, визначених у модулі:
>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
При цьому
імпортуються
усі назви, крім
тих, що починаються
з нижньої риски
(_
).
Доріжка пошуку модулів
Якщо імпортується
модуль, що зветься
spam
, то інтерпретатор
спочатку шукає
файл з назвою
spam.py
у поточній
директорії,
а потім у директоріях,
визначених
змінною середовища
PYTHONPATH
. Вона має
такий же синтаксис,
як і змінна
оболонки PATH
,
тобто являє
собою список
директорій.
Якщо PYTHONPATH
не
задано, або
якщо файл там
не знайдено,
то пошук продувжується
по типовій
доріжці, яка
залежить від
інсталяції;
у системах Unix
це здебільшого
.:/usr/local/lib/python
.
Тут слід уточнити,
що пошук модулів
починається
зі списку директорій,
заданих змінною
sys.path
, яка ініціалізується
із директорії,
де розміщено
скрипт вводу
(чи у поточній
директорії),
а вже потім
продовжується
у PYTHONPATH
та у залежному
від інсталяції
місці. Це дозволяє
програмам
змінювати
доріжку пошуку.
Зауважте, що
оскільки назва
директорії,
де знаходиться
виконуваний
скрипт, є на
шляху доріжки
пошуку, то важливо,
щоб назва скрипта
не збігалася
з назвою певного
стандартного
модуля, бо інакше
Пітон спробує
завантажити
скрипт замість
модуля при
імпорті. Загалом
це повинно
призвести до
помилки. Див.
розділ "Стандартні
модулі" для
докладнішої
інформації.
"Компільовані" файли
Існує можливість
значного прискорення
запуску коротких
програм, що
використовують
багато стандартних
модулів: якщо
в директорії,
де знаходиться
файл spam.py
,
існує файл
spam.pyc
, то
вважається,
що він містить
скомпільовану
на рівні байтів
версію модуля
spam
. Час останьої
зміни версії
spam.py
, що
використовується
для створення
spam.pyc
, записується
у spam.pyc
, і
файл .pyc
пропускається,
якщо час зміни
скомпільованої
версії не відповідає
текстовій.
У більшості
випадків для
створення файла
spam.pyc
не
треба нічого
робити. Як тільки
spam.py
скомпільовано
без проблем,
інтерпретатор
зробить спробу
записати
скомпільовану
версію у spam.pyc
.
Якщо ця спроба
не вдається,
то це не призводить
до помилки.
Якщо з певних
причин файл
не записано
повністю, то
новостворений
spam.pyc
буде
вважатися
недійсним і
таким чином
не буде використовуватися
пізніше. Вміст
файла spam.pyc
не залежить
від платформи,
отже директорія,
що містить
модулі, написані
на Пітоні, може
використовуватися
машинами різних
архітектур.
Окремі поради для експертів:
- Якщо інтерпретатор викликається з опцією -O, то оптимізований код буде створено і записано в файлах з розширенням
.pyo
. Наразі оптимізатор не дуже допомагає, він лише видаляє твердженняassert
. При викоистанні -O оптимізуються усі байтові коди; файли.pyc
пропускаються, а з файлів.py
компілюється оптимізований байтовий код. - Подання подвійної опції -O інтерпретатору Пітона (-OO) призведе до оптимізації, що в окремих випадках може спричинити неполадки у програмі. Наразі видаляються лише ланцюжки
__doc__
, що призводить до створення більш компактних файлів.pyo
. Оскільки програми можуть покладатися на існування цих змінних, цю опцію слід лише використовувати лише якщо ви точно знаєте, що робите. - Швидкість виконання програми не змінюється, коли її зчитано з файлів
.pyc
чи.pyo
, а не.py
. Єдине, що відбувається швидше - це завантаження програми. - Якщо скрипт запускається через подання його назви з командного рядка, то його байтовий код ніколи не записується у файл
.pyc
чи.pyo
. Таким чином, прискорення запуску скрипта можна досягнути, якщо помістити більшість коду в окремий модуль і створити невеликий стартовий файл, що імпортує той модуль. Також можливо ввести назву файла.pyc
чи.pyo
з командного рядка. - Можливо також викликати файл
spam.pyc
(чиspam.pyo
якщо використано -O) навіть якщо файлspam.py
для цього ж модуля відсутній. Це може використовуватися для розповсюдження бібліотеки коду Пітона, з якого не зовсім просто відтворити код-джерело. - Модуль
compileall
може створити файли.pyc
(чи.pyo
, якщо використано -O) для всіх модулів, що знаходяться у певній директорії.
Стандартні модулі
Пітон має бібліотеку стандартних модулів, яка описана в окремому
документі, що зветься "Довідник бібліотеки мови Python" (Python Library Reference)
(надалі "Довідник бібліотеки"). Окремі модулі , що вбудовано в
інтерпретатор, надають доступ до операцій, що не є основною
частиною мови, але все таки вони вбудовані, чи то
задля ефективності, чи для того, щоб надати доступ до примітивів
операційної системи, зокрема системних викликів. Такі модулі є частиною
конфігурації, що залежить від платформи. Наприклад, модуль
amoeba
існує лише у системах, що певним чином підтримують
примітиви системи Amoeba. Один окремий модуль заслуговує спеціальної
уваги: 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')
Функція 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']
Зауважте, що цей список містить всі типи назв: змінні, модулі, функції тощо.
dir()
не видає назв вбудованих функцій та
змінних. Якщо ці назви потрібні, то вони визначені у стандартному
модулі __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']
Пакети
Пакети - це засіб організації іменного простору модулів Пітона
шляхом використання "нотації крапками" ("dotted module names).
Наприклад, назва модуля A.B
вказує на
підмодуль "B
" у пакеті "A
".
Подібно до того як використання модулів позбавляє авторів зайвих тривог
щодо
назв глобальних змінних, визначених кимось іншим, використання назв
модулів, з'єднаних крапками, допомагає авторам багатомодульних пакетів
(як, скажімо, NumPy чи графічної бібліотеки Python Imaging Library)
уникати проблем,
пов'язяних з використанням однакових назв модулів.
Скажімо, ви хочете створити колекцію модулів (пакет) для обробки
звукових даних та звукових файлів. Існує багато різних звукових
форматів файлів (здебільшого вони розпізнаються за розширенням,
напр.: .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
...
При імпортуванні пакета Пітон шукає його піддиректорію, перебираючи
директорії, що містяться у sys.path
.
Файли __init__.py
потрібні, щоб Пітон міг
розпізнати директорії, як такі, що містять в собі пакети; це зроблено з
метою запобігання випадковому заміщенню інших модулів,
розташованих
далі на пошуковій доріжці, директоріями, що мають загальні назви
(напр., "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
пакетimport
елемент`,
елемент може бути підмодулем (чи підпакетом) пакета або якоюсь іншою
назвою, визначеною в пакеті, як, скажімо, функція, клас чи змінна.
Твердження
importспершу перевіряє, чи визначено заданий
елемент у пакеті; якщо ні - цей елемент вважається модулем, і робиться
спроба його завантаження. Якщо ж і модуля не знайдено,то відкидається
виняток "помилка імортування"
ImportError`.
З іншого боку, при використанні синтаксису import
елемент.піделемент.підпіделемент``,
кожен елемент окрім останього повинен бути пакетом. Останній елемент
може бути модулем чи пакетом, але не може бути класом, функцією чи
змінною, визначеною у попередньому елементі.
Імпортування * з пакета
Що ж відбувається, коли користувач пише from Sound.Effects import *
?
В ідеальному випадку можна сподіватися, що тут певним чином
відбувається
пошук файлової системи, знайдено всі підмодулі пакета, і всіх їх
імпортовано. На жаль, ця операція не зовсім добре працює на платформах
Mac та Windows, де файлова система не завжди має акуратну інформацію
щодо розрізнення великих та малих літер в назві файла! На цих
платформах немає певного способу визначення, яким саме чином потрібен
бути імпортований файл ECHO.PY
: як модуль echo
,
Echo
чи ECHO
.
(Наприклад, Windows 95 має прикру звичку показувати назви файлів з
великої літери). Обмеження назв файлів у DOS 8+3 додає іншу цікаву
проблему інтерпретації довгих назв модулів.
Єдиним вирішенням проблеми є явне подання автором змісту пакета.
Твердження import використовує таку конвенцію: якщо код пакета
__init__.py
визначає список, що зветься __all__
,
то він вважається списком назв модулів, що потрібно імпортувати при
використанні твердження from
пакетimport *
.
Утримання повного списку модулів є відповідальністю автора. Автори
пакетів можуть також обмежити import *
зі своїх пакетів.
Наприклад,
файл Sounds/Effects/__init__.py
може містити
такий код:
__all__ = ["echo", "surround", "reverse"]
Це означає, що from Sound.Effects import *
імпортує
лише три вказані підмодулі пакета Sound
.
Якщо __all__
невизначено, то твердження from
Sound.Effects
import *
не імпортує
усі підмодулі пакета Sound.Effects
у поточний
іменний простір, а лише забезпечує імпорт пакета Sound.Effects
(можливо шляхом його ініціалізазії з __init__.py
)
і потім імпортує всі назви, визначені в пакеті. Це включає всі назви
визначені (та явно завантажені підмодулі) у файлі __init__.py
.
Це також включає будь-які підмодулі пакета, що були явно завантажені
попередніми твердженнями імпортування. Розгляньмо такий код:
import Sound.Effects.echo
import Sound.Effects.surround
from Sound.Effects import *
У цьому прикладі модулі echo та surround імпортуються у поточний
простір назв тому, що вони визначені у пакеті Sound.Effects
при виконанні твердження from...import
. (Це діє також,
коли визначено __all__
).
Зауважте, що звичка імпортувати * з модулів не заохочується, оскільки це часто призводить до нечитабельного коду. Хоча це можна використовувати, щоб зберегти час, потрібний для вводу під час діалогового режиму, до того ж певні модулі навмисно створені, щоб експортувати модулі відповідно до певних зразків.
Пам'ятайте, що немає нічого поганого, якщо ви використовуєте from
Пакет import певний_підмодуль
! Загалом, саме така форма
імпортування
є рекомендованою, за винятком коли імпортуючий модуль потребує
підмодуль з тією самою назвою, але з іншого пакета.
Внутрішньопакетні посилання
Підмодулі часто посилаються один на одного. Наприклад, модуль
surround
може посилатися на модуль echo
.
Такі посилання є настільки поширеними, що
твердження import
спочатку перевіряє
зовнішній^containing пакет перед тим, як розпочати пошук стандартної
доріжки модулів. Таким чином, модуль surround
може просто використовувати import echo
чи
from echo import echofilter
. Якщо імпортований модуль не
знайдено в поточному пакеті (для якого поточний модуль є
підмодулем), то твердження import
шукає
модуль найвищого рівня^toplevel з цією назвою.
Якщо пакети зорганізовано у підпакети (як у наведеному прикладі з
пакетом Sound
), то посилання «навпростець» на
пакет-близнюк неможливе — тут повинна використовуватися повна назва
пакета. Наприклад, якщо модулю
Sound.Filters.vocoder
потрібен модуль echo
у пакеті Sound.Effects
,
то для цього можна використовувати from Sound.Effects import echo
.
Пакети, що знаходяться у різних директоріях
Пакети підтримують ще однин спеціальний атрибут: __path__
.
Він ініціалізується списоком, що містить назву директорії, у якій
знаходиться __init__.py
даного пакета, перед
виконанням коду,
що знаходиться у цьому файлі. Ця змінна можу бути змінена, що
позначиться на майбутніх пошуках підпакетів даного пакета.
Хоча ця риса потрібна нечасто, вона може використовуватися для розширення кількості модулів, що складають даний пакет.