Программирование на Python 3. Руководство издательство СимволПлюс
![]()
|
• Модули и пакеты • Обзор стандартной библиотеки языка Python 230 Глава 5. Модули полнительно будут приводиться ссылки на описания модулей в других главах. Модули и пакеты Модуль в языке Python – это обычный файл с расширением .py. Мо дуль может содержать любой программный код на языке Python. Ка ждая программа, которую мы писали до сих пор, находилась в отдель ном файле .py, который можно считать не только программой, но и мо дулем. Основное различие между модулем и программой состоит в том, что программа предназначена для того, чтобы ее запускали, тогда как модуль предназначен для того, чтобы его импортировали и использо вали в программах. Не все модули располагаются в файлах с расширением .py, например, модуль sys встроен в Python, а некоторые модули написаны на других языках программирования (чаще всего на языке C). Однако большая часть библиотеки языка Python написана именно на языке Python, так, например, добавляя инструкцию import collections, мы получаем возможность создавать именованные кортежи вызовом функции col lections.namedtuple() , а функциональные возможности, к которым мы получаем доступ, находятся в файле модуля collections.py. Для наших программ совершенно неважно, на каком языке программирования написан модуль, потому что все модули импортируются и используют ся одним и тем же способом. Импортирование может выполняться несколькими синтаксическими конструкциями, например: import importable import importable1, importable2, ..., importableN import importable as preferred_name Здесь под importable подразумевается имя модуля, такое как collections, но точно так же это может быть пакет или модуль из пакета, и тогда все части имени отделяют ся друг от друга точками (.), например, os.path. Первые две конструкции мы используем на протяжении всей книги. В них нет ничего сложного, и они являются са мыми безопасными, потому что позволяют избежать конфликтов имен, так как вынуждают программиста всегда использовать полные квалифицированные имена. Третья конструкция позволяет давать импортируемому модулю или пакету имя по выбору – теоретически это может привести к конфлик там имен, но на практике синтаксис as обычно используется, чтобы как раз избежать их. Подобное переименование, в частности, удобно использовать при экспериментировании с различными реализациями одного и того же модуля. Например, допустим, что у нас имеется два модуля MyModuleA и MyModuleB, которые имеют один и тот же API (Appli Пакеты, стр. 234 Модули и пакеты 231 cation Programming Interface – прикладной программный интерфейс); мы могли бы в программе записать инструкцию import MyModuleA as My Module , а позднее легко переключиться на использование import MyModu leB as MyModule Где должна находиться инструкция import? Обычно все инструкции import помещаются в начало файла .py, после строки «shebang» и после описания модуля. И, как уже говорилось в главе 1, мы рекомендуем сначала импортировать модули стандартной библиотеки, затем моду ли сторонних разработчиков и в последнюю очередь свои собственные модули. Ниже приводятся еще несколько вариантов использования инструк ции import: from importable import object as preferred_name from importable import object1, object2, ..., objectN from importable import (object1, object2, object3, object4, object5, object6, ..., objectN) from importable import * Эти синтаксические конструкции могут приводить к конфликтам имен, поскольку они обеспечивают непосредственный доступ к импор тируемым объектам (переменным, функциям, типам данных или мо дулям). Если для импортирования большого числа объектов необходи мо использовать синтаксис from ... import, мы можем расположить инструкцию импорта в нескольких строках, либо экранируя каждый символ перевода строки, кроме последнего, либо заключая список имен объектов в круглые скобки, как показано в третьем примере. В последней синтаксической конструкции символ «*» означает «импортировать все имена, которые не являют ся частными». На практике это означает, что будут им портированы все объекты из модуля за исключением тех, чьи имена начинаются с символа подчеркивания, либо, если в модуле определена глобальная переменная __all__ со списком имен, будут импортированы все объ екты, имена которых перечислены в переменной __all__. Ниже приводятся несколько примеров использования инструкции import : import os print(os.path.basename(filename)) # безопасный доступ по полным # квалифицированным именам import os.path as path print(path.basename(filename)) # есть риск конфликта имен с модулем path from os import path print(path.basename(filename)) # есть риск конфликта имен с модулем path from os.path import basename print(basename(filename)) # есть риск конфликта имен с модулем basename Функция __all__() , стр. 236 232 Глава 5. Модули from os.path import * print(basename(filename)) # есть риск множественных конфликтов имен Синтаксис from importable import * используется для импортирования всех объектов из модуля (или из всех модулей пакета) – это могут быть сотни имен. В случае from os.path import * будет импортировано почти 40 имен, включая имена dirname, exists и split, которые, вполне веро ятно, мы могли бы использовать в качестве имен для наших собствен ных переменных или функций. Например, если записать инструкцию from os.path import dirname , мы получим удобную возможность вызывать функцию dirname(), не ука зывая полное квалифицированное имя. Но если ниже в нашем про граммном коде будет встречена инструкция dirname = "." , то после ее выполнения ссылка на объект dirname будет указывать уже не на функ цию dirname(), а на строку ".". Поэтому, если мы попытаемся вызвать функцию dirname(), мы получим исключение TypeError, потому что те перь имя dirname ссылается на строку, а не на вызываемый объект. Ввиду того, что синтаксис import * потенциально опасен появлением конфликтов имен, некоторые коллективы разработчиков вырабатыва ют свои правила, устанавливающие, что в их разработках может ис пользоваться только синтаксис import importable. Однако некоторые крупные пакеты, в частности библиотеки GUI (Graphical User Inter face – графический интерфейс пользователя), нередко импортируются таким способом, потому что они включают огромное число функций и классов (собственных типов данных), для которых было бы слишком утомительно вводить вручную полные имена. Возникает естественный вопрос – как интерпретатор узнает, где ис кать импортируемые модули и пакеты? Встроенный модуль sys имеет список с именем sys.path, в котором хранится перечень каталогов, со ставляющих путь поиска Python. Первый каталог в этом списке – это каталог, где находится сама программа, даже если она вызывается из другого каталога. Далее в списке находятся пути к каталогам из пере менной окружения PYTHONPATH, если она определена. И в конце списка находятся пути к каталогам стандартной библиотеки языка Python – они определяются на этапе установки Python. Когда модуль импортируется впервые, если он не является встроенным, интерпретатор пытается отыскать его поочередно в каждом из каталогов, перечисленных в списке sys.path. Как следствие этого, если мы создаем модуль или программу, имя которого совпадает с именем библиотечного модуля, наш мо дуль будет найден первым, что неизбежно будет приводить к проблемам. Чтобы избежать этого, никогда не создавайте программы или модули, имена которых совпадают с именами модулей или каталогов верхнего уровня в библиотеке, если только вы не пытаетесь подставить свою собственную реализа цию и ваше переопределение преднамеренно. (Модулем верх Модули и пакеты 233 него уровня называется файл .py, который находится в одном из ката логов, включенных в путь поиска Python, а не в какомнибудь подка талоге, вложенном в один из этих каталогов.) Например, в системе Windows в путь поиска Python обычно включается каталог с именем C:\Python30\Lib , поэтому на этой платформе мы не должны создавать модуль с именем Lib.py, так же как модуль, имя которого совпадает с именем любого модуля из каталога C:\Python30\Lib. Один из способов быстро проверить, используется ли то или иное имя модуля, состоит в том, чтобы попытаться импортировать модуль. Сде лать это можно в консоли, вызвав интерпретатор с ключом – c («execu te code» – выполнить программный код), за которым следует указать инструкцию import. Например, если необходимо проверить, существу ет ли модуль с именем Music.py (или каталог верхнего уровня Music в пути поиска Python), можно ввести в консоли следующую команду: python c "import Music" Если в ответ будет получено исключение ImportError, можно быть уве ренным, что модуль или каталог верхнего уровня с таким именем не используется; любой другой вывод (или его отсутствие) означает нали чие такого имени. К сожалению, такой прием не дает полной гаран тии, что впоследствии с этим именем не будет возникать никаких про блем, поскольку позднее мы можем установить пакет или модуль, соз данный сторонним разработчиком, имеющий такое же имя, хотя на практике такая проблема возникает достаточно редко. Например, если мы создадим модуль os.py, он будет конфликтовать с библиотечным модулем os. Но если мы создадим модуль path.py, то никаких проблем возникать не будет, поскольку этот модуль при шлось бы импортировать как модуль path, тогда как библиотечный мо дуль должен импортироваться как os.path. В этой книге имена файлов наших собственных модулей всегда будут начинаться с символа верх него регистра; это позволит избежать конфликтов имен (по крайней мере в UNIX), потому что имена файлов библиотечных модулей состо ят исключительно из символов нижнего регистра. Программа может импортировать некоторые модули, которые в свою очередь импортируют другие модули, включая те, что уже были им портированы. Это не является проблемой. Всякий раз, когда выполня ется попытка импортировать модуль, интерпретатор Python сначала проверяет – не был ли импортирован требуемый модуль ранее. Если модуль еще не был импортирован, Python выполняет скомпилирован ный байткод модуля, создавая тем самым переменные, функции и другие объекты модуля, после чего добавляет во внутреннюю струк туру запись о том, что модуль был импортирован. При любых после дующих попытках импортировать этот модуль интерпретатор будет обнаруживать, что модуль уже импортирован и не будет выполнять никаких действий. 234 Глава 5. Модули Когда интерпретатору требуется скомпилированный байткод модуля, он генерирует его автоматически – этим Python отличается от таких языков программирования, как Java, где компилирование в байткод должно выполняться явно. Сначала интерпретатор попытается оты скать файл, имя которого совпадает с именем файла, имеющего рас ширение .py, но имеющий расширение .pyo – это оптимизированный байткод скомпилированной версии модуля. Если файл с расширени ем .pyo не будет найден (или он более старый, чем файл с расширением .py ), интерпретатор попытается отыскать одноименный файл с расши рением .pyc – это неоптимизированный байткод скомпилированной версии модуля. Если интерпретатор обнаружит актуальную скомпи лированную версию модуля, он загрузит ее; в противном случае Py thon загрузит файл с расширением .py и скомпилирует его в байткод. В любом случае интерпретатор загрузит в память модуль в виде ском пилированного байткода. Если интерпретатор выполнил компиляцию файла с расширением .py, он сохранит скомпилированную версию в одноименном файле с рас ширением .pyc (или .pyo, если интерпретатор был запущен с ключом командной строки – O 1 , или если в переменной окружения PYTHONOPTI MIZE установлено значение O), при этом каталог должен быть доступен для записи. Сохранения байткода можно избежать, если запускать интерпретатор с ключом командной строки – B или установив перемен ную окружения PYTHONDONTWRITEBYTECODE. Использование файлов со скомпилированным байткодом ускоряет за пуск программы, поскольку интерпретатору остается только загру зить и выполнить программный код, минуя этап компиляции (и со хранения, если это возможно), хотя сама скорость работы программы от этого не зависит. При установке Python компиляция модулей стан дартной библиотеки в байткод обычно является частью процесса уста новки. Пакеты Пакет – это простой каталог, содержащий множество модулей и файл с именем __init__.py. Например, допустим, что у нас имеется некото рое множество файлов модулей, предназначенных для чтения и записи графических файлов различных форматов с именами Bmp.py, Jpeg.py, Png.py , Tiff.py и Xpm.py, в каждом из которых имеются функции load() , save() и т. д. 2 Мы могли бы сохранить все эти модули в одном каталоге с программой, но в крупных программных продуктах, ис 1 Это символ «O», а не цифра 0. – Прим. перев. 2 Широкая поддержка операций с графическими файлами обеспечивается различными модулями сторонних разработчиков, из которых наиболее примечательной является библиотека Python Imaging Library (www.python ware.com/products/pil ). Модули и пакеты 235 пользующих массу собственных модулей, модули для работы с графи кой, скорее всего, лучше хранить отдельно. Поместив их в свой собст венный подкаталог, например Graphics, их можно хранить все вместе. А если поместить в каталог Graphics пустой файл __init__.py, этот ка талог превратится в пакет: Graphics/ __init__.py Bmp.py Jpeg.py Png.py Tiff.py Xpm.py Пока каталог Graphics является подкаталогом каталога с программой или находится в пути поиска Python, мы будем иметь возможность импортировать любой из этих модулей и использовать их. Мы должны сделать все возможное, чтобы гарантировать несовпадение имени на шего модуля верхнего уровня (Graphics) с какимлибо из имен верхнего уровня в стандартной библиотеке – с целью избежать конфликтов имен. (В системе UNIX это легко обеспечить, достаточно лишь исполь зовать в качестве первого символа имени символ верхнего регистра, так как в именах модулей стандартной библиотеки используются только символы нижнего регистра.) Ниже показано, как импортиро вать и использовать наши модули: import Graphics.Bmp image = Graphics.Bmp.load("bashful.bmp") В небольших программах некоторые программисты предпочитают ис пользовать более короткие имена, и язык Python позволяет делать это двумя, немного отличающимися способами. import Graphics.Jpeg as Jpeg image = Jpeg.load("doc.jpeg") Здесь мы импортировали модуль Jpeg из пакета Graphics и сообщили интерпретатору, что вместо полного квалифицированного имени Graphics.Jpeg хотим использовать более короткое имя Jpeg. from Graphics import Png image = Png.load("dopey.png") Этот фрагмент программного кода напрямую импортирует модуль Png из пакета Graphics. Данная синтаксическая конструкция (import ... from ) обеспечивает непосредственный доступ к модулю Png. Мы не обязаны использовать в нашем программном коде оригиналь ные имена модулей. Например: from Graphics import Tiff as picture image = picture.load("grumpy.tiff") 236 Глава 5. Модули Здесь мы используем модуль Tiff, но внутри нашей программы пере именовали его в модуль picture. В некоторых ситуациях бывает удобно загружать все модули пакета одной инструкцией. Для этого необходимо отредактировать файл __init__.py пакета, записав в него инструкцию, которая указывала бы, какие модули должны загружаться. Эта инструкция должна присваи вать список с именами модулей специальной переменной __all__. На пример, ниже приводится необходимая строка для файла Graphics/ __init__.py : __all__ = ["Bmp", "Jpeg", "Png", "Tiff", "Xpm"] Этим ограничивается необходимое содержимое файла __init__.py, по мимо этого, мы можем поместить в него любой программный код, ка кой только пожелаем. Теперь мы можем использовать другую разно видность инструкции import: from Graphics import * image = Xpm.load("sleepy.xpm") Синтаксис from package import * напрямую импортирует все имена мо дулей, упомянутые в списке __all__. То есть после выполнения этой инструкции мы получим прямой доступ не только к модулю Xpm, но и ко всем другим модулям. Как отмечалось ранее, этот синтаксис может применяться и к моду лям, то есть from module import *, в этом случае будут импортированы все функции, переменные и другие объекты, определяемые модулем (за исключением тех, чьи имена начинаются с символа подчеркива ния). При необходимости точно указать, что должно быть импортиро вано при использовании синтаксической конструкции from module im port * , мы можем определить список __all__ непосредственно в моду ле; в этом случае инструкция from module import * будет импортировать только те объекты, имена которых присутствуют в списке __all__. До сих пор мы демонстрировали только один уровень вложенности, но Python позволяет создавать столько уровней вложенности пакетов, сколько нам заблагорассудится. То есть мы можем поместить в ката лог Graphics подкаталог, скажем, Vector, с файлами модулей внутри него Eps.py и Svg.py: Graphics/ __init__.py Bmp.py Jpeg.py Png.py Tiff.py Vector/ __init__.py Eps.py Модули и пакеты 237 Svg.py Xpm.py Чтобы каталог Vector превратился в пакет, в него необходимо помес тить файл __init__.py, который, как уже говорилось, может быть пус тым или определять список __all__ для обеспечения удобства тем про граммистам, которые предпочтут использовать инструкцию импорти рования from Graphics.Vector import *. Для доступа к вложенному пакету мы можем использовать обычный синтаксис, который использовали ранее: import Graphics.Vector.Eps image = Graphics.Vector.Eps.load("sneezy.eps") Полные квалифицированные имена могут оказаться слишком длин ными, поэтому некоторые программисты пытаются привести иерар хию модулей к плоскому виду, чтобы избежать необходимости вруч ную вводить такие имена: import Graphics.Vector.Svg as Svg image = Svg.load("snow.svg") Мы всегда можем использовать свои собственные короткие имена для модулей, как показано в этом примере, хотя это повышает риск появ ления конфликтов имен. |