Главная страница
Навигация по странице:

  • Модули и инструкция import

  • Импортирование отдельных имен из модулей

  • Выполнение модуля как самостоятельной программы

  • Выгрузка и повторная загрузка модулей

  • Распространение программ и библиотек на языке Python

  • Аргумент Описание

  • справочник по Python. мм isbn 9785932861578 9 785932 861578


    Скачать 4.21 Mb.
    Названиемм isbn 9785932861578 9 785932 861578
    Анкорсправочник по Python
    Дата08.05.2022
    Размер4.21 Mb.
    Формат файлаpdf
    Имя файлаBizli_Python-Podrobnyy-spravochnik.440222.pdf
    ТипСправочник
    #518195
    страница16 из 82
    1   ...   12   13   14   15   16   17   18   19   ...   82
    Глава
    8
    .
    Модули, пакеты и дистрибутивы
    Крупные программы на языке Python обычно организованы в виде набо-
    Python обычно организованы в виде набо- обычно организованы в виде набо- ра модулей и пакетов. Кроме того, большое число модулей также входит в стандартную библиотеку Python. В этой главе более подробно рассказы-
    Python. В этой главе более подробно рассказы-
    . В этой главе более подробно рассказы- вается о системе модулей и пакетов. Помимо этого здесь приводится инфор- мация о том, как устанавливать модули сторонних разработчиков и как создавать дистрибутивы с исходными текстами.
    Модули и инструкция import
    Любой файл с исходными текстами на языке Python может использоваться как модуль. В качестве примера рассмотрим содержимое файла spam.py:
    # spam.py a = 37
    def foo():
    print(“Функция foo(), a = %s” % a)
    def bar():
    print(“Функция bar(), вызывается функция foo()”)
    foo()
    class Spam(object):
    def grok(self):
    print(“Метод Spam.grok”)
    Загрузить файл с этим исходным программным кодом, как модуль, можно с помощью инструкции import spam. Когда инструкция import впервые за- гружает модуль, она выполняет следующие три операции:
    1. Создает новое пространство имен, которое будет служить контейнером для всех объектов, определяемых в соответствующем файле. Это – то пространство имен, которое будет доступно функциям и методам, объ- явленным в модуле, использующим инструкцию global.
    2. Выполняет программный код в модуле внутри вновь созданного про- странства имен.

    190
    Глава 8. Модули, пакеты и дистрибутивы
    3. Создает в вызывающей программе имя, ссылающееся на пространство имен модуля. Это имя совпадает с именем модуля и используется, как показано ниже:
    import spam # Загрузит и выполнит модуль ‘spam’
    x = spam.a # Обратится к переменной модуля ‘spam’
    spam.foo() # Вызовет функцию в модуле ‘spam’
    s = spam.Spam() # Создаст экземпляр класса spam.Spam()
    s.grok()
    ...
    Важно подчеркнуть, что инструкция import выполнит все инструкции в за- груженном файле. Если в дополнение к объявлению переменных, функций и классов в модуле содержатся некоторые вычисления и вывод результатов, то результаты будут выведены на экран в момент загрузки модуля. Кроме этого, обычное недопонимание работы с модулями связано со способом обра- щения к классам, объявленным в нем. Запомните, что если в файле spam.py объявлен класс Spam, обращаться к этому классу следует по имени spam.Spam.
    Чтобы импортировать сразу несколько модулей, их имена можно перечис- лить в инструкции import через запятую, например:
    import socket, os, re
    Имя, используемое для ссылки на модуль, можно изменить с помощью квалификатора as. Например:
    import spam as sp import socket as net sp.foo()
    sp.bar()
    net.gethostname()
    Когда модуль загружается под другим именем, как в примере выше, новое имя можно использовать только в файле или в контексте, где находится инструкция import. Другие модули по-прежнему могут загружать модуль под его оригинальным именем.
    Возможность изменения имени импортируемого модуля может оказаться полезным инструментом, позволяющим писать расширяемый программ- ный код. Например, допустим, что имеется два модуля, xmlreader.py и csv- reader.py
    , каждый из которых объявляет функцию read_data(filename), ко- торая читает некоторые данные из файла, но работает с файлами разных форматов. Можно написать такой программный код, который будет выби- рать необходимый модуль чтения, как показано ниже:
    if format == ‘xml’:
    import xmlreader as reader elif format == ‘csv’:
    import csvreader as reader data = reader.read_data(filename)
    Модули в языке Python – это «первоклассные» объекты. То есть они мо- гут присваиваться переменным, помещаться в структуры данных, такие как списки, и передаваться между частями программы в виде элемента

    Импортирование отдельных имен из модулей
    191
    данных. Например, переменная reader в предыдущем примере – это про- сто ссылка на соответствующий объект модуля. С точки зрения внутрен- ней реализации объект модуля – это словарь, который хранит содержимое пространства имен модуля. Этот словарь доступен как атрибут __dict__ модуля, и всякий раз, когда производится обращение к значению внутри модуля, вы фактически работаете с этим словарем.
    Инструкция import может появляться в любом месте программы. Однако программный код любого модуля загружается и выполняется только один раз, независимо от количества инструкций import, загружающих его. Все последующие инструкции import будут просто связывать имя модуля с объ- ектом модуля, созданным первой встретившейся инструкцией import. Сло- варь, содержащий все модули, загруженные к текущему моменту, досту- пен в виде переменной sys.modules. Этот словарь отображает имена модулей на объекты модулей. Содержимое этого словаря используется, чтобы опре- делить, должна ли инструкция import загружать свежую копию модуля.
    Импортирование отдельных имен из модулей
    Для загрузки отдельных определений из модуля в текущее пространство имен используется инструкция from. По своей функциональности инструк- ция from идентична инструкции import, за исключением того, что вместо создания имени, ссылающегося на вновь созданное пространство имен мо- дуля, она помещает ссылки на один или более объектов, объявленных в мо- дуле, в текущее пространство имен:
    from spam import foo # Импортирует модуль spam и помещает имя ‘foo’
    # в текущее пространство имен foo() # Вызовет spam.foo()
    spam.foo() # NameError: spam
    Инструкция from также может принимать список имен объектов, разделен- ных запятыми. Например:
    from spam import foo, bar
    Если список импортируемых имен достаточно длинный, его можно заклю- чить в круглые скобки. Благодаря этому инструкцию import можно разме- стить в нескольких строках программы. Например:
    from spam import (foo,
    bar,
    Spam)
    Кроме того, в инструкции from можно использовать квалификатор as, что- бы присвоить импортируемым объектам другие имена. Например:
    from spam import Spam as Sp s = Sp()
    Помимо этого, для загрузки всех определений, имеющихся в модуле, за исключением тех, имена которых начинаются с символа подчеркивания, можно использовать шаблонный символ звездочки (*). Например:

    192
    Глава 8. Модули, пакеты и дистрибутивы from spam import * # Загрузит все определения в текущее пространство имен
    Инструкция from module import * может использоваться только для загруз- ки модулей верхнего уровня. В частности, инструкцию импортирования в таком виде нельзя использовать внутри функций – из-за ограничений, накладываемых правилами видимости (например, когда функция компи- лируется в байт-код, все имена, используемые в функции, должны быть квалифицированы полностью).
    Модули позволяют организовать более точное управление набором имен, импортируемых инструкцией from module import *, посредством объявле- ния списка __all__. Например:
    # module: spam.py
    __all__ = [ ‘bar’, ‘Spam’ ] # Эти имена будут импортироваться инструкцией
    # from spam import *
    Правила видимости для определений, импортированных инструкцией from
    , не изменяются. Например, рассмотрим следующий фрагмент:
    from spam import foo a = 42
    foo() # Выведет “Функция foo(), a = 37”
    В данном примере функция foo(), объявленная в модуле spam.py, обращает- ся к глобальной переменной a. Когда ссылка на функцию foo() помещается в другое пространство имен, это не приводит к изменению правил види- мости переменных внутри функции. То есть глобальным пространством имен для функции всегда будет модуль, в котором она была объявлена, а не пространство имен, в которое эта функция была импортирована и откуда была вызвана. То же самое относится и к вызовам функций. Например, в следующем фрагменте вызывается функция bar(), которая в свою очередь вызывает функцию spam.foo(), а не переопределенную функцию foo(), объ- явленную в следующем примере:
    from spam import bar def foo():
    print(“Другая функция foo”)
    bar() # Когда функция bar() вызовет функцию foo(), то будет вызвана
    # spam.foo(), а не функция foo(), объявленная выше
    Другой типичный источник ошибок, связанных с инструкцией from, каса- ется поведения глобальных переменных. Рассмотрим в качестве примера следующий фрагмент:
    from spam import a, foo # Импортирует глобальную переменную a = 42 # Изменит значение переменной foo() # Выведет “Функция foo(), a = 37”
    print(a) # Выведет “42”
    Здесь важно понять, что инструкция присваивания значения переменной в языке Python не является операцией сохранения значения. То есть ин-
    Python не является операцией сохранения значения. То есть ин- не является операцией сохранения значения. То есть ин- струкция присваивания в предыдущем примере не сохраняет новое значе- ние в переменной a, затирая старое значение. Вместо этого создается новый объект, содержащий значение 42, а в переменную a записывается ссылка

    Выполнение модуля как самостоятельной программы
    193
    на него. После этого переменная a потеряет связь со значением, импортиро- ванным из модуля, и будет ассоциирована с некоторым другим объектом.
    По этой причине невозможно с помощью инструкции from имитировать по- ведение глобальных переменных или общих блоков, такое, как в языках программирования C или Fortran. Если в программе потребуется иметь из-
    C или Fortran. Если в программе потребуется иметь из- или Fortran. Если в программе потребуется иметь из-
    Fortran. Если в программе потребуется иметь из-
    . Если в программе потребуется иметь из- меняемые глобальные параметры, их можно поместить в модуль и явно ис- пользовать имя модуля, импортированного с помощью инструкции import
    (то есть явно использовать имя spam.a).
    Выполнение модуля
    как самостоятельной программы
    Интерпретатор Python может выполнять файлы с программным кодом двумя способами. Инструкция import выполняет программный код библи- отечного модуля в собственном пространстве имен. Однако программный код может также выполняться как отдельная программа или сценарий.
    Это происходит, когда имя файла передается интерпретатору как имя сце- нария:
    % python spam.py
    Для каждого модуля определяется переменная __name__, где хранится имя модуля. Программы могут проверять значение этой переменной, чтобы определить, в каком режиме они выполняются. При выполнении интер- претатором модуль верхнего уровня получает имя __main__. Программа, имя которой было передано интерпретатору в виде аргумента командной строки, или введенная в интерактивной оболочке, выполняется внутри пространства имен модуля __main__. Иногда бывает необходимо изменить поведение программы, в зависимости от того, была ли она импортирована как модуль или запущена в пространстве имен __main__. Например, модуль может содержать какие-либо тесты, которые должны выполняться при за- пуске модуля как отдельной программы и не должны выполняться, когда модуль импортируется другим модулем. Реализовать это можно, как по- казано ниже:
    # Проверить, был ли модуль запущен как программа if __name__ == ‘__main__’:
    # Да
    инструкции
    else:
    # Нет, файл был импортирован как модуль
    инструкции
    В файлы с программным кодом, которые могут использоваться как би- блиотеки, часто включается дополнительный программный код, с при- мерами или тестами. Например, при разработке модуля можно поместить программный код, производящий тестирование библиотеки, внутрь ин- струкции if, как показано выше, и просто запускать модуль, как само- стоятельную программу, чтобы выполнить его. Этот программный код не будет выполняться, когда пользователь будет импортировать библиотеку как модуль.

    194
    Глава 8. Модули, пакеты и дистрибутивы
    Путь поиска модулей
    Чтобы загрузить модуль, интерпретатор просматривает каталоги, список которых находится в переменной sys.path. Первым элементом в списке sys.
    path обычно является пустая строка ‘’, которая обозначает текущий рабо- чий каталог. Остальные элементы списка sys.path могут содержать имена каталогов, архивных файлов в формате .zip и файлов пакетов с расшире- нием .egg. Порядок следования элементов в sys.path определяет порядок по- иска файла при загрузке модуля. Чтобы добавить элемент в путь поиска, достаточно просто добавить его в этот список.
    Несмотря на то что путь обычно включает имена каталогов, в путь поиска можно также добавлять zip-архивы, содержащие модули Python. Эта осо- zip-архивы, содержащие модули Python. Эта осо-
    -архивы, содержащие модули Python. Эта осо-
    Python. Эта осо-
    . Эта осо- бенность может использоваться для упаковки коллекции модулей в еди- ный файл. Например, предположим, что вы создали два модуля, foo.py и bar.py, и поместили их в zip-файл с именем mymodules.zip. Этот файл мож- но будет добавить в путь поиска Python, как показано ниже:
    import sys sys.path.append(“mymodules.zip”)
    import foo, bar
    Также допускается указывать конкретное местоположение в структуре ка- талогов, внутри zip-файла. Кроме того, zip-файлы можно указывать впе- zip-файла. Кроме того, zip-файлы можно указывать впе-
    -файла. Кроме того, zip-файлы можно указывать впе- zip-файлы можно указывать впе-
    -файлы можно указывать впе- ремежку с обычными компонентами пути в файловой системе. Например: sys.path.append(“/tmp/modules.zip/lib/python”)
    Кроме .zip-файлов, в путь поиска можно также добавлять файлы с рас- ширением .egg. Файлы с расширением .egg – это пакеты, созданные с по- мощью библиотеки setuptools. С этим распространенным форматом па- кетов вы встретитесь, когда будете устанавливать сторонние библиотеки и расширения Python. Файлы с расширением .egg – это, по сути, обычные zip-файлы, содержащие дополнительные метаданные (например, номер версии, список зависимостей и так далее). То есть данные, находящиеся в файле с расширением .egg, можно извлекать с помощью стандартных ин- струментов, предназначенных для работы с zip-файлами.
    Несмотря на наличие возможности импортировать zip-файлы, они имеют некоторые ограничения, о которых следует знать. Во-первых, из архивов можно импортировать только файлы с расширениями .py, .pyw, .pyc и .pyo.
    Разделяемые библиотеки и модули расширений, написанные на языке C, не могут загружаться из архивов, хотя некоторые системы пакетов, та- кие как setuptools, предоставляют обходные пути решения этой проблемы
    (обычно извлекая расширения на языке C во временный каталог и загру-
    C во временный каталог и загру- во временный каталог и загру- жая модули из него). Кроме того, интерпретатор Python не будет создавать файлы с расширениями .pyc и .pyo, если файлы .py были загружены из ар- хива (пояснения в следующем разделе). Поэтому очень важно убедиться, что эти файлы были созданы заранее и упакованы в архив, чтобы не иметь потерь в производительности при загрузке модулей.

    Загрузка и компиляция модулей
    195
    Загрузка и компиляция модулей
    До сих пор в этой главе рассматривались модули, которые представляют собой файлы с программным кодом исключительно на языке Python. Од-
    Python. Од-
    . Од- нако в действительности модули, загружаемые инструкцией import, могут быть отнесены к четырем основным категориям:
    • Программный код на языке Python (файлы с расширением .py)
    • Расширения на языке C или C++, которые были скомпилированы в виде разделяемых библиотек или DLL
    • Пакеты, содержащие коллекции модулей
    • Встроенные модули, написанные на языке C и скомпонованные с интер-
    C и скомпонованные с интер- и скомпонованные с интер- претатором Python
    При поиске модуля (например, foo) интерпретатор просматривает каждый каталог, упомянутый в списке sys.path, в поисках следующих файлов (пе- речисленных в том порядке, в каком ведется поиск):
    1. Каталог foo, объявленный как пакет.
    2. foo.pyd, foo.so, foomodule.so или foomodule.dll (скомпилированные рас- скомпилированные рас- рас- рас- ширения).
    3. foo.pyo (только если при компиляции был использован ключ -O или -OO).
    4. foo.pyc.
    5. foo.py (в Windows интерпретатор также проверяет наличие файлов с расширением .pyw).
    Пакеты будут описаны чуть ниже; скомпилированные расширения описа- ны в главе 26 «Расширение и встраивание Python». Что касается файлов с расширением .py, то когда модуль импортируется впервые, он компили- руется в байт-код и сохраняется на диске в файле с расширением .pyc. При всех последующих обращениях к импортированию этого модуля интерпре- татор будет загружать скомпилированный байт-код, если только с момента создания байт-кода в файл .py не вносились изменения (в этом случае файл
    .pyc будет создан заново). Файлы .pyo создаются, когда интерпретатор запу- скается с ключом -O. В этом случае из байт-кода удаляются номера строк, инструкции assert и прочая отладочная информация. В результате файлы получаются меньше и выполняются интерпретатором немного быстрее.
    Если вместо ключа -O использовать ключ -OO, из файла также будут уда- лены строки документирования. Удаление строк документирования про- исходит именно при создании файлов с расширением .pyo, но не во время их загрузки. Если интерпретатору не удастся обнаружить ни один из этих файлов в каталогах, перечисленных в списке sys.path, он проверит, не соот- ветствует ли это имя встроенному модулю. Если такого встроенного моду- ля не существует, будет возбуждено исключение ImportError.
    Автоматическая компиляция программного кода в файлы с расширения- ми .pyc и .pyo производится только при использовании инструкции import.
    При запуске программ из командной строки эти файлы не создаются. Кро-

    196
    Глава 8. Модули, пакеты и дистрибутивы ме того, эти файлы не создаются, если каталог, содержащий файл .py моду- ля, не доступен для записи (например, из-за нехватки прав у пользователя или когда модуль находится в zip-архиве). Запретить создание этих файлов можно также, запустив интерпретатор с ключом -B.
    Если имеются файлы .pyc и .pyo, файлы .py с исходными текстами могут от- сутствовать. То есть, если вы не желаете включать в пакет исходные тексты модулей, можно просто упаковать набор файлов .pyc. Однако следует пом- нить, что интерпретатор Python обладает мощной возможностью интро-
    Python обладает мощной возможностью интро- обладает мощной возможностью интро- спекции и дизассемблирования. Опытные пользователи без особого труда смогут исследовать ваши модули и узнать массу подробностей о них, даже в случае отсутствия исходных текстов. Кроме того, не нужно забывать, что файлы .pyc могут зависеть от версии интерпретатора. То есть файл .pyc, созданный одной версией интерпретатора Python, может оказаться нерабо-
    Python, может оказаться нерабо-
    , может оказаться нерабо- чим с будущими версиями.
    Когда инструкция import пытается отыскать файлы, поиск производится с учетом регистра символов в именах файлов, даже в операционных систе- мах, где файловые системы не различают регистр символов, в таких как
    Windows и OS X (хотя такие системы сохраняют регистр символов). Поэто- и OS X (хотя такие системы сохраняют регистр символов). Поэто-
    OS X (хотя такие системы сохраняют регистр символов). Поэто-
    X (хотя такие системы сохраняют регистр символов). Поэто-
    X (хотя такие системы сохраняют регистр символов). Поэто-
    (хотя такие системы сохраняют регистр символов). Поэто- му инструкция import foo сможет импортировать только файл foo.py и не сможет –FOO.PY. Вообще желательно избегать использования символов раз- личных регистров в именах модулей.
    Выгрузка и повторная загрузка модулей
    В языке Python отсутствует полноценная поддержка возможности повтор-
    Python отсутствует полноценная поддержка возможности повтор- отсутствует полноценная поддержка возможности повтор- ной загрузки или выгрузки модулей, импортированных ранее. Даже если удалить модуль из словаря sys.modules, в общем случае это не приведет к вы- грузке модуля из памяти. Это может быть обусловлено наличием ссылок на объект модуля в других компонентах программы, которые загрузили этот модуль с помощью инструкции import. Более того, если в программе были созданы экземпляры классов, объявленных в модуле, эти экземпляры со- держат ссылки на соответствующие им объекты классов, которые в свою очередь хранят ссылки на модуль, в котором они были объявлены.
    Наличие ссылок на модуль в разных местах программы делает практиче- ски невозможной повторную загрузку модуля после внесения изменений в его реализацию. Например, если удалить модуль из словаря sys.modules и вызвать инструкцию import, чтобы опять загрузить его, это не окажет влияния на ссылки, которые были созданы в программе до этого. Вместо этого вы получите ссылку на новый модуль, созданный самой последней инструкцией import, и множество ссылок на старую версию модуля из дру- гих мест программы. Скорее всего, окажется нежелательным и наверняка небезопасным использование в реальных условиях реально функциониру- ющего кода, в котором нет полного контроля над средой выполнения.
    Старые версии Python предоставляли функцию reload(), позволяющую выгружать модули. Однако эта функция никогда не была безопасной в ис- пользовании (по всем вышеупомянутым причинам), и ее настоятельно ре-

    Пакеты
    197
    комендовали использовать исключительно для отладки. В версии Python 3 такая возможность была полностью ликвидирована. Поэтому лучше ни- лучше ни- лучше ни- ни- ни- когда не полагаться на нее.
    Наконец, следует отметить, что расширения для Python, написанные на языке C/C++, не могут быть безопасно выгружены и повторно загружены никаким способом. Такая возможность никогда не поддерживалась и не поддерживается, к тому же этому может препятствовать сама операцион- ная система. Поэтому ваша единственная возможность – это полностью перезапустить процесс интерпретатора Python.
    Пакеты
    Пакеты позволяют сгруппировать коллекцию модулей под общим именем пакета. Этот прием позволяет решить проблему конфликтов имен между именами модулей, используемых в различных приложениях. Пакет соз- дается как каталог с тем же именем, в котором создается файл с именем
    __init__.py
    . Затем в этом каталоге можно сохранить исходные файлы, ском- пилированные расширения и подпакеты. Например, пакет может иметь такую структуру:
    Graphics/
    __init__.py
    Primitive/
    __init__.py lines.py fill.py text.py
    ...
    Graph2d/
    __init__.py plot2d.py
    ...
    Graph3d/
    __init__.py plot3d.py
    ...
    Formats/
    __init__.py gif.py png.py tiff.py jpeg.py
    Загрузка модулей из пакета может быть выполнена с помощью инструк- ции import несколькими способами:
    • import Graphics.Primitive.fill
    Загрузит модуль Graphics.Primitive.fill. Объекты, содержащие-
    Объекты, содержащие-
    , содержащие- содержащие- ся в этом модуле, получат имена, такие как Graphics.Primitive.fill.
    floodfill(img,x,y,color)

    198
    Глава 8. Модули, пакеты и дистрибутивы
    • from Graphics.Primitive import fill
    Загрузит модуль fill, но сделает возможным обращаться к нему без использования префикса с именем пакета; например, fill.
    floodfill(img,x,y,color)
    • from Graphics.Primitive.fill import floodfill
    Загрузит модуль fill, но сделает возможным обращаться к функции floodfill непосредственно; например, floodfill(img,x,y,color).
    Всякий раз когда какая-либо часть пакета импортируется впервые, вы- полняется программный код в файле __init__.py. Этот файл может быть пустым, но может также содержать программный код, выполняющий инициализацию пакета. Выполнены будут все файлы __init__.py, которые встретятся инструкции import в процессе ее выполнения. То есть инструк- ция import Graphics.Primitive.fill, показанная выше, сначала выполнит файл __init__.py в каталоге Graphics, а затем файл __init__.py в каталоге
    Primitive
    Существует одна проблема, характерная для пакетов, связанная с выпол- нением такой инструкции:
    from Graphics.Primitive import *
    Когда программист использует подобную инструкцию, он обычно хочет импортировать все модули, ассоциированные с пакетом, в текущее про- странство имен. Однако из-за того, что соглашения по именованию файлов могут изменяться от системы к системе (особенно это относится к регистру символов), Python не в состоянии точно определить, какие модули долж-
    Python не в состоянии точно определить, какие модули долж- не в состоянии точно определить, какие модули долж- ны загружаться. Как результат, эта инструкция просто импортирует все имена, которые определены в файле __init__.py, находящемся в каталоге
    Primitive
    . Это поведение можно изменить, определив список __all__, содер- жащий имена всех модулей в пакете. Этот список должен быть объявлен в файле __init__.py пакета, например:
    # Graphics/Primitive/__init__.py
    __all__ = [“lines”,”text”,”fill”]
    Теперь, когда интерпретатор встретит инструкцию from Graphics.Primitive import *
    , он загрузит все перечисленные модули, как и следовало ожидать.
    Еще одна малозаметная проблема, связанная с пакетами, касается моду- лей, которые должны импортировать другие модули из того же пакета.
    Например, допустим, что модуль Graphics.Primitive.fill должен импорти- ровать модуль Graphics.Primitive.lines. Для этого можно просто указать полностью квалифицированное имя модуля (например, from Graphics.Primi-
    Graphics.Primi-
    Graphics.Primi-
    .Primi-
    Primi- tives import lines
    ) или выполнить импортирование относительно текущего пакета, например:
    # fill.py from . import lines
    В этом примере символ . в инструкции from . import lines ссылается на тот же каталог, где находится вызывающий модуль. То есть данная инструк-

    Пакеты
    199
    ция будет искать модуль lines в том же каталоге, где находится файл fill.
    py
    . При импортировании модулей из пакета следует быть особенно внима- тельными и не использовать инструкцию вида import module. В старых вер- сиях Python было не очевидно, ссылается ли инструкция import module на модуль в стандартной библиотеке или на модуль в пакете. В старых верси- ях Python такая инструкция сначала пыталась загрузить модуль из того же каталога пакета, где находится импортирующий модуль, и только по- том, в случае неудачи, делалась попытка загрузить модуль из стандартной библиотеки. Однако в Python 3, инструкция import предполагает, что ука- зан абсолютный путь, и будет пытаться загрузить модуль из стандартной библиотеки. Использование инструкции импортирования по относитель- ному пути более четко говорит о ваших намерениях.
    Возможность импортирования по относительному пути можно также ис- пользовать для загрузки модулей, находящихся в других каталогах того же пакета. Например, если в модуле Graphics.Graph2D.plot2d потребуется им- портировать модуль Graphics.Primitives.lines, инструкция импорта будет иметь следующий вид:
    # plot2d.py from ..Primitives import lines
    В этом примере символы .. перемещают точку начала поиска на уровень выше в дереве каталогов, а имя Primitives перемещает ее вниз, в другой ка- талог пакета.
    Импорт по относительному пути может выполняться только при исполь- зовании инструкции импортирования вида from module import symbol. То есть такие инструкции, как import ..Primitives.lines или import .lines, бу- дут рассматриваться как синтаксическая ошибка. Кроме того, имя symbol должно быть допустимым идентификатором. Поэтому такая инструкция, как from .. import Primitives.lines, также считается ошибочной. Наконец, импортирование по относительному пути может выполняться только для модулей в пакете; не допускается использовать эту возможность для ссыл- ки на модули, которые просто находятся в другом каталоге файловой си- стемы.
    Импортирование по одному только имени пакета не приводит к импорти- рованию всех модулей, содержащихся в этом пакете. Например, следую- щий фрагмент не будет работать:
    import Graphics
    Graphics.Primitive.fill.floodfill(img,x,y,color) # Ошибка!
    Однако, так как инструкция import Graphics выполнит файл __init__.py в каталоге Graphics, в него можно добавить инструкции импортирования по относительному пути, которые автоматически загрузят все модули, как показано ниже:
    # Graphics/__init__.py from . import Primitive, Graph2d, Graph3d
    ёё
    # Graphics/Primitive/__init__.py from . import lines, fill, text, ...

    200
    Глава 8. Модули, пакеты и дистрибутивы
    Те перь инструкция import Graphics будет импортировать все модули и обе- спечит их доступность по полностью квалифицированным именам. Еще раз подчеркну, что инструкция импортирования пакета по относительно- му пути должна использоваться именно так, как показано выше. Если ис- пользовать простую инструкцию, такую как import module, она попытается загрузить модуль из стандартной библиотеки.
    Наконец, когда интерпретатор импортирует пакет, он объявляет специ- альную переменную __path__, содержащую список каталогов, в которых выполняется поиск модулей пакета (__path__ представляет собой аналог списка sys.path для пакета). Переменная __path__ доступна для программ- ного кода в файлах __init__.py и изначально содержит единственный эле- мент с именем каталога пакета. При необходимости пакет может добавлять в список __path__ дополнительные каталоги, чтобы изменить путь поиска модулей. Это может потребоваться в случае сложной организации дерева каталогов пакета в файловой системе, которая не совпадает с иерархией пакета.
    Распространение программ и библиотек
    на языке Python
    Чтобы подготовить дистрибутив программы для передачи ее другому лицу, необходимо воспользоваться модулем distutils. Для начала необходимо подготовить структуру каталогов, создать в нем файл README, скопировать туда документацию и файлы с исходными текстами. Обычно этот каталог будет содержать смесь библиотечных модулей, пакетов и сценариев. Мо- дули и пакеты относятся к исходным файлам, которые загружаются ин- струкциями import. Сценарии – это файлы с программным кодом, которые будут запускаться интерпретатором, как самостоятельные программы (на- пример, как команда python имя_сценария). Ниже приводится пример ката- лога, содержащего программный код на языке Python:
    spam/
    README.txt
    Documentation.txt libspam.py # Одиночный библиотечный модуль spampkg/ # Пакет вспомогательных модулей
    __init__.py foo.py bar.py runspam.py # Сценарий, который запускается как: python runspam.py
    Программный код должен быть организован так, чтобы он нормально работал при запуске интерпретатора Python в каталоге верхнего уровня.
    Например, если запустить интерпретатор в каталоге spam, он должен быть в состоянии импортировать модули, компоненты пакета и запускать сце- нарии без изменения каких-либо настроек Python, таких как путь поиска модулей.

    Распространение программ и библиотек на языке Python
    201
    После того как каталог будет подготовлен, нужно создать файл setup.py в самом верхнем каталоге (в предыдущем примере – это каталог spam) и по- местить в него следующий программный код:
    # setup.py from distutils.core import setup
    ёё
    setup(name = “spam”,
    version = “1.0”,
    py_modules = [‘libspam’],
    packages = [‘spampkg’],
    scripts = [‘runspam.py’],
    )
    Аргумент py_modules в функции setup() – это список всех файлов одиночных модулей, packages – список всех каталогов пакетов и scripts – список фай- список фай- фай- фай- лов сценариев. Любой из этих аргументов может быть опущен, если ваш программный продукт не включает соответствующие ему компоненты (на- пример, не имеет сценариев). Аргумент name – это имя пакета, а version – номер версии в виде строки.
    Функция setup() может принимать ряд других аргументов, содержащих дополнительные метаданные о пакете. В табл. 8.1 перечислены наиболее часто используемые аргументы. Все аргументы принимают строковые зна- используемые аргументы. Все аргументы принимают строковые зна- используемые аргументы. Все аргументы принимают строковые зна- аргументы. Все аргументы принимают строковые зна- аргументы. Все аргументы принимают строковые зна-
    . Все аргументы принимают строковые зна-
    Все аргументы принимают строковые зна- чения, за исключением classifiers, который является списком строк, на- пример: [‘Development Status :: 4 - Beta’, ‘Programming Language :: Python’]
    (полный список аргументов можно найти по адресу http://pypi.python.org).
    Таблица 8.1. Аргументы функции setup()
    Аргумент
    Описание
    name
    Имя пакета (обязательный)
    version
    Номер версии (обязательный)
    author
    Имя автора author_email
    Адрес электронной почты автора maintainer
    Имя лица, осуществляющего сопровождение maintainer_email
    Адрес электронной почты лица, осуществляющего сопровождение url
    Адрес домашней страницы проекта пакета description
    Краткое описание пакета long_description
    Полное описание пакета download_url
    Адрес, откуда можно загрузить пакет classifiers
    Список строк классификаторов
    Файла setup.py вполне достаточно для создания дистрибутива с исходными текстами программного обеспечения. Чтобы создать дистрибутив, введите следующую команду в командной оболочке:

    202
    Глава 8. Модули, пакеты и дистрибутивы
    % python setup.py sdist
    ...
    %
    В результате в каталоге spam/dist будет создан архивный файл, такой как spam-1.0.tar.gz или spam-1.0.zip. Это и есть файл дистрибутива, который можно передать другому лицу для установки вашего программного обеспе- чения. Чтобы установить программу из дистрибутива, пользователь дол- жен просто распаковать архив и выполнить следующие действия:
    % unzip spam-1.0.zip
    ...
    % cd spam-1.0
    % python setup.py install
    ...
    %
    В результате программное обеспечение будет установлено на локальном компьютере и готово к использованию. Модули и пакеты обычно устанав- ливаются в каталог с именем “site-packages” в библиотеке Python. Чтобы определить точное местоположение этого каталога, можно проверить зна- чение переменной sys.path. В UNIX-подобных операционных системах сце-
    UNIX-подобных операционных системах сце-
    -подобных операционных системах сце- нарии обычно устанавливаются в каталог установки интерпретатора Py-
    Py- thon, а в Windows – в каталог “Scripts” (обычно это каталог “C:\Python26\
    Scripts”
    ).
    В операционной системе UNIX, если первая строка сценария начинается с последовательности символов #! и содержит текст “python”, мастер уста- новки запишет в эту строку действительный путь к интерпретатору Python на локальном компьютере. То есть, если во время разработки в сценарии был жестко задан путь к интерпретатору Python, такой как /usr/local/
    bin/python
    , после установки на другом компьютере, где Python установлен в другой каталог, этот сценарий сохранит свою работоспособность.
    Файл setup.py реализует множество других команд, касающихся созда- ния дистрибутивов. Если выполнить команду ‘python setup.py bdist’, будет создан двоичный дистрибутив, где все файлы .py будут скомпилированы в файлы с расширением .pyc и помещены в дерево каталогов, имитирую- щее структуру каталогов на локальном компьютере. Такой способ созда- ния дистрибутивов может потребоваться, только если в приложении име- ются компоненты, зависящие от типа платформы (например, если имеется расширение на языке C, которое должно распространяться в скомпилиро-
    C, которое должно распространяться в скомпилиро-
    , которое должно распространяться в скомпилиро- ванном виде). Если в Windows запустить команду ‘python setup.py bdist_
    wininst’
    , будет создан исполняемый файл с расширением .exe. Если затем этот файл запустить в Windows, откроется диалог мастера установки, где пользователю будет предложено указать каталог, куда следует выполнить установку. Кроме всего прочего, при установке дистрибутивов этого типа в реестр Windows добавляются дополнительные записи, впоследствии упрощающие возможность удаления пакета.
    Модуль distutils предполагает, что на компьютере пользователя уже уста- новлен интерпретатор Python (загруженный отдельно). Безусловно, суще-
    Python (загруженный отдельно). Безусловно, суще-
    (загруженный отдельно). Безусловно, суще- ствует возможность создать выполняемый файл, который вместе с вашим

    Установка сторонних библиотек
    203
    программным продуктом будет включать в себя все необходимые компо- ненты Python, однако рассмотрение этой темы выходит далеко за рамки данной книги (дополнительную информацию можно найти в описаниях к сторонним модулям, таким как py2exe или py2app). Если под распростра- нение подпадают только библиотеки или простые сценарии, вам скорее всего не потребуется упаковывать в дистрибутив с программным кодом ин- терпретатор Python и дополнительные компоненты.
    В заключение следует отметить, что модуль distutils обладает намного бо- лее широкими возможностями, чем было описано здесь. В главе 26 описы- вается, как можно использовать модуль distutils для сборки расширений, написанных на языке C и C++.
    Несмотря на отсутствие необходимых инструментов в составе стандартной установки Python, имеется возможность распространять свое программное обеспечение в виде файлов с расширением .egg. Файлы этого формата соз- даются с помощью популярного расширения setuptools (http://pypi.python.
    org/pypi/setuptools
    ). Чтобы обеспечить поддержку setuptools, достаточно просто изменить первую часть файла setup.py, как показано ниже:
    # setup.py try:
    from setuptools import setup except ImportError:
    from distutils.core import setup
    ёё
    setup(name = “spam”,
    ...
    )
    Установка сторонних библиотек
    Наиболее полным ресурсом, где можно найти сторонние библиотеки и рас- ширения для Python, является каталог пакетов Python (Python Package
    Index – PyPI), доступный по адресу http://pypi.python.org. Установка сто- ронних модулей обычно выполняется достаточно просто, но может превра- титься в сложную задачу при установке крупных пакетов, зависящих от других сторонних модулей. Большинство основных расширений снабжа- ются программами установки для выбранной платформы, которые помо- гут выполнить установку, проведя вас через последовательность диалогов.
    Чтобы установить другие модули, обычно бывает достаточно распаковать архив, отыскать файл setup.py и ввести команду python setup.py install.
    По умолчанию сторонние модули устанавливаются в каталог site-packag-
    -packag- packag- es
    , в стандартной библиотеке Python. Для записи в этот каталог обычно требуются привилегии суперпользователя или администратора. Если вы не обладаете этими привилегиями, можно ввести команду python setup.py
    install --user
    , чтобы установить модуль в библиотечный каталог пользова- теля. В этом случае пакет будет установлен в домашний каталог пользова- теля, например: “/Users/beazley/.local/lib/python2.6/site-packages” в UNIX.
    Если потребуется установить программное обеспечение в совершенно иное место, можно воспользоваться параметром --prefix сценария setup.py. На-

    204
    Глава 8. Модули, пакеты и дистрибутивы пример, команда pythonsetup.py install --prefix=/home/beazley/pypackages установит модуль в каталог /home/beazley/pypackages. Когда установка вы- полняется в нестандартный каталог, наверняка может потребоваться из- менить значение параметра настройки sys.path, чтобы интерпретатор смог отыскать вновь установленные модули.
    Следует помнить, что многие расширения Python написаны на языке C или C++. Если вы загрузили дистрибутив с исходными текстами, то чтобы выполнить установку такого расширения, в вашей системе должен быть установлен компилятор C++. В UNIX, Linux и OS X это требование обычно не вызывает проблем. В Windows для этого традиционно требуется устано-
    Windows для этого традиционно требуется устано- для этого традиционно требуется устано- вить версию Microsoft Visual Studio. Если вы пользуетесь Windows, веро-
    Microsoft Visual Studio. Если вы пользуетесь Windows, веро-
    Visual Studio. Если вы пользуетесь Windows, веро-
    Visual Studio. Если вы пользуетесь Windows, веро-
    Studio. Если вы пользуетесь Windows, веро-
    Studio. Если вы пользуетесь Windows, веро-
    . Если вы пользуетесь Windows, веро-
    Windows, веро-
    , веро- ятно, будет лучше, если вы попробуете отыскать уже скомпилированную версию расширения.
    Если у вас было установлено расширение setuptools, для установки паке- тов можно использовать сценарий easy_install. Чтобы установить какой- то конкретный пакет, достаточно ввести команду easy_install имя_пакета.
    Если setuptools имеет корректные настройки, сценарий загрузит требуе- мый пакет из каталога PyPI, вместе со всеми зависимостями, и установит его. Конечно, время установки при этом может изменяться.
    Если у вас появится желание поместить свои разработки в каталог PyPI, просто введите команду python setup.py register. Она выгрузит метаданные о последней версии вашего программного продукта в каталог (обратите внимание, что перед этим вы должны зарегистрироваться на сайте и по- лучить имя пользователя и пароль).

    1   ...   12   13   14   15   16   17   18   19   ...   82


    написать администратору сайта