Підручник мови Python/Модулі

Матеріал з Вікіпідручника

Загальні зауваження[ред.]

Якщо ви залишите інтерпретатор Пайтона, а потім увійдете в нього знову, усі зроблені вами визначення функцій та змінних буде втрачено. Тому, якщо ви хочете написати дещо довшу програму, то для цього краще використовувати текстовий редактор і виконати програму, записану у файлі. Це зветься створенням скрипта. Коли програма збільшується, то ви можливо захочете розбити її на кілька файлів, щоб полегшити її підтримку. Можливо, ви маєте кілька зручних функцій, що ви створили у різних програмах, і ви хочете їх використати без копіювання їхніх описів у різні програми.

Для підтримки цього, Пайтон має певний механізм для створення визначень у файлі, які згодом можуть використовуватися у скрипті чи у діалоговому режимі інтерпретатора. Такий файл зветься модулем. Визначення, задані в модулі, імпортуються в інші модулі або в основний (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 та залежним від інсталяції шляхом. Це дозволяє програмам змінювати адресу пошуку. Зауважте, що оскільки назва директорії, де знаходиться виконуваний скрипт, є у змінній sys.path, то важливо, щоб назва скрипта не збігалася з назвою певного стандартного модуля, бо інакше Пайтон спробує завантажити скрипт замість модуля при імпорті. Загалом це повинно призвести до помилки. Див. розділ "Стандартні модулі" для докладнішої інформації.

"Компільовані" файли[ред.]

Існує можливість значного прискорення запуску коротких програм, що використовують багато стандартних модулів: якщо в директорії, де знаходиться файл 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) навіть якщо файл 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.

Єдиним вирішенням проблеми є явне задання автором змісту пакета. Інструкція 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 спочатку перевіряє зовнішній[1] пакет перед тим, як розпочати пошук в sys.path. Таким чином, модуль surround може просто використовувати import echo чи from echo import echofilter. Якщо імпортований модуль не знайдено в поточному пакеті (для якого поточний модуль є підмодулем), то інструкція import шукає модуль найвищого рівня[2] з цією назвою.

Якщо пакети зорганізовано у підпакети (як у наведеному прикладі з пакетом Sound), то посилання «навпростець» на пакет-близнюк неможливе — тут повинна використовуватися повна назва пакета. Наприклад, якщо модулю Sound.Filters.vocoder потрібен модуль echo у пакеті Sound.Effects, то для цього можна використовувати from Sound.Effects import echo.

Пакети, що знаходяться у різних директоріях[ред.]

Пакети підтримують ще однин спеціальний атрибут: __path__. Він ініціалізується списком, який містить назву директорії, у якій знаходиться __init__.py даного пакета, перед виконанням коду, що знаходиться у цьому файлі. Ця змінна може бути змінена, що позначиться на майбутніх пошуках підпакетів даного пакета.

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

Зноски[ред.]

  1. в ориґіналі — containing. (Прим. перекл.)
  2. В ориґіналі — top-level module. (Прим. перекл.)