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

  • Смешанные режимы использования: __name__ и __main__

  • Тестирование модулей с помощью __name__

  • Изменение пути поиска модулей

  • Синтаксис относительного импорта

  • Зачем необходим относительный импорт

  • Математический анализ. 3е издание


    Скачать 4.86 Mb.
    Название3е издание
    АнкорМатематический анализ
    Дата04.02.2022
    Размер4.86 Mb.
    Формат файлаpdf
    Имя файлаpython_01.pdf
    ТипДокументы
    #351981
    страница65 из 98
    1   ...   61   62   63   64   65   66   67   68   ...   98
    Включение будущих возможностей языка
    В языке периодически появляются изменения, которые могут повли
    ять на работоспособность существующего программного кода. Сначала они появляются в виде расширений, которые по умолчанию отключе
    ны. Чтобы включить такие расширения, используется инструкция импорта специального вида:

    Смешанные режимы использования: _ _name_ _ и _ _main_ _
    535
    from __future__ import имя_функциональной_особенности
    Эта инструкция вообще должна появляться в самом начале файла мо
    дуля (возможно, сразу же вслед за строкой документирования), потому что она включает специальный режим компиляции программного кода для каждого отдельно взятого модуля. Возможно также выполнить эту инструкцию в интерактивной оболочке, что позволит поэксперименти
    ровать с грядущими изменениями в языке; включенная особенность будет после этого доступна в течение всего интерактивного сеанса.
    Например, в предыдущем издании этой книги мы использовали эту форму инструкции для демонстрации функцийгенераторов, в которых используется ключевое слово, еще недоступное по умолчанию в то вре
    мя (в качестве имя_функциональной_особенности указывалось имя genera
    tors
    ). Мы уже использовали эту инструкцию для включения операции истинного деления чисел в главе 5 и будем использовать ее и в этой гла
    ве для включения возможности абсолютного импорта, а также в седь
    мой части книги – для демонстрации менеджеров контекста.
    Все эти изменения могут отрицательно сказаться на работоспособности существующего программного кода, и поэтому они так постепенно вво
    дятся в язык – сначала в виде дополнительных возможностей, вклю
    чаемых с помощью этой специальной формы инструкции импорта.
    Смешанные режимы использования:
    __name__ и __main__
    Ниже демонстрируется специальный прием, позволяющий импорти
    ровать файлы как модули и запускать их как самостоятельные про
    граммы. Каждый модуль обладает встроенным атрибутом __name__, ко
    торый устанавливается интерпретатором следующим образом:

    Если файл запускается как главный файл программы, атрибуту
    __name__
    на запуске присваивается значение "__main__".

    Если файл импортируется, атрибуту __name__ присваивается имя модуля, под которым он будет известен клиенту.
    Благодаря этому модуль может проверить собственный атрибут
    __name__
    и определить, был он запущен как самостоятельная програм
    ма или импортирован другим модулем. Например, предположим, что мы создаем файл модуля с именем runme.py, который экспортирует единственную функцию с именем tester:
    def tester():
    print "It's Christmas in Heaven..."
    if __name__ == '__main__': # Только когда запускается,
    tester() # а не импортируется
    Этот модуль определяет функцию для клиентов и может импортиро
    ваться как обычный модуль:

    536
    Глава 21. Дополнительные возможности модулей
    % python
    >>> import runme
    >>> runme.tester()
    It's Christmas in Heaven...
    Но в самом конце модуля имеется программный код, который вызыва
    ет функцию, когда этот файл запускается как самостоятельная про
    грамма:
    % python runme.py
    It's Christmas in Heaven...
    Пожалуй, чаще всего проверка атрибута __name__ выполняется в про
    граммном коде для самопроверки модуля. Проще говоря, вы можете добавить в конец модуля программный код, который будет выполнять проверку экспортируемых элементов внутри самого модуля, заключив этот код в условную инструкцию, проверяющую атрибут __name__. При таком подходе вы можете использовать файл в других модулях, импор
    тируя его, и тестировать логику работы, запуская его из командной строки или какимлибо другим способом. На практике программный код самопроверки в конце файла, заключенный в условную инструк
    цию, проверяющую атрибут __name__, является, пожалуй, самым рас
    пространенным и удобным способом модульного тестирования в языке
    Python. (В главе 29 обсуждаются другие часто используемые способы тестирования программного кода на языке Python – как будет показа
    но, в стандартной библиотеке существуют модули unittest и doctest,
    которые реализуют более совершенные средства тестирования.)
    Прием, основанный на проверке атрибута __name__, также часто ис
    пользуется при создании файлов, которые могут использоваться и как утилиты командной строки, и как библиотеки инструментов. Напри
    мер, предположим, что вы пишете на языке Python сценарий поиска файлов. Код принесет больше пользы, если реализовать его в виде функций и добавить проверку атрибута __name__ для организации вы
    зова этих функции, когда файл запускается как самостоятельная про
    грамма. При таком подходе сценарий может повторно использоваться в составе других программ.
    Тестирование модулей с помощью __name__
    Мы уже видели в этой книге один хороший пример, применительно к которому проверка атрибута __name__ могла бы быть полезной. В раз
    деле, рассказывающем об аргументах, в главе 16, мы написали сцена
    рий, который находит минимальное значение среди множества пред
    ложенных аргументов:
    def minmax(test, *args):
    res = args[0]
    for arg in args[1:]:
    if test(arg, res):
    res = arg

    Смешанные режимы использования: _ _name_ _ и _ _main_ _
    537
    return res def lessthan(x, y): return x < y def grtrthan(x, y): return x > y print minmax(lessthan, 4, 2, 1, 5, 6, 3) # Код самопроверки
    print minmax(grtrthan, 4, 2, 1, 5, 6, 3)
    В самом конце этого сценария присутствует программный код само
    проверки, благодаря которому мы можем проверить правильность ра
    боты модуля без необходимости вводить его в интерактивной оболочке всякий раз, когда нам потребуется проверить модуль. Однако при та
    кой реализации имеется одна проблема – результаты самопроверки будут выводиться на экран всякий раз, когда этот файл будет импор
    тироваться для использования другим файлом, но тогда это становит
    ся невежливым по отношению к пользователю! Чтобы исправить поло
    жение, можно обернуть проверочные вызовы функции в условную ин
    струкцию, проверяющую атрибут __name__ так, чтобы они выполня
    лись, только когда файл запускается как самостоятельная программа,
    а не во время импорта:
    print 'I am:', __name__
    def minmax(test, *args):
    res = args[0]
    for arg in args[1:]:
    if test(arg, res):
    res = arg return res def lessthan(x, y): return x < y def grtrthan(x, y): return x > y if __name__ == '__main__':
    print minmax(lessthan, 4, 2, 1, 5, 6, 3) # Код самопроверки
    print minmax(grtrthan, 4, 2, 1, 5, 6, 3)
    Здесь в самом начале добавлена инструкция вывода значения атрибу
    та __name__, чтобы проверить его визуально. Интерпретатор Python соз
    дает эту переменную и присваивает ей значение во время загрузки файла. Когда файл запускается как самостоятельная программа, это
    му имени присваивается значение '__main__', поэтому в данном случае происходит автоматическое выполнение кода самопроверки:
    % python min.py
    I am: __main__
    1 6
    Однако, когда файл импортируется, значение атрибута __name__ уже не равно '__main__', поэтому необходимо явно вызвать функцию, чтобы запустить ее:
    >>> import min

    538
    Глава 21. Дополнительные возможности модулей
    I am: min
    >>> min.minmax(min.lessthan, 's', 'p', 'a', 'm')
    'a'
    Неважно, будет ли использоваться этот прием для нужд тестирования,
    главный результат – что наш программный код может использоваться и как библиотека инструментов, и как самостоятельная программа.
    Изменение пути поиска модулей
    В главе 18 мы узнали, что путь поиска модулей – это список катало
    гов, и что этот список можно дополнить с помощью переменной окру
    жения PYTHONPATH и файлов .pth. Но я пока еще не показывал, как сами программы на языке Python могут изменять путь поиска, изменяя встроенный список с именем sys.path (атрибут path встроенного моду
    ля sys). Список sys.path инициализируется во время запуска програм
    мы, однако после этого допускается удалять, добавлять и изменять компоненты списка по своему усмотрению:
    >>> import sys
    >>> sys.path
    ['', 'D:\\PP3ECDPartial\\Examples', 'C:\\Python25', ...далее опущено...]
    >>> sys.path.append('C:\\sourcedir') # Дополнение пути поиска модулей
    >>> import string # Новый каталог будет участвовать
    # в поиске
    Как только будут внесены изменения, они будут воздействовать на все последующие инструкции импорта, выполняемые в программе, так как все инструкции во всех файлах программы используют один и тот же общий список sys.path. Этот список может изменяться произволь
    ным образом:
    >>> sys.path = [r'd:\temp'] # Изменяет путь поиска модулей
    >>> sys.path.append('c:\\lp3e\\examples') # Только для этой программы
    >>> sys.path
    ['d:\\temp', 'c:\\lp3e\\examples']
    >>> import string
    Traceback (most recent call last):
    File "", line 1, in ?
    ImportError: No module named string
    Таким образом, этот прием может использоваться для динамической настройки пути поиска внутри программ на языке Python. Однако будьте внимательны: если убрать из пути критически важный ката
    лог, можно потерять доступ к критически важным утилитам. В пре
    дыдущем примере, например, был потерян доступ к модулю string, по
    тому что из пути был удален исходный каталог библиотеки.
    Кроме того, не забывайте, что такие изменения списка sys.path действу
    ют только в рамках интерактивного сеанса или внутри программы (тех

    Расширение import as
    539
    нически – в рамках процесса), где были выполнены эти изменения, –
    они не сохраняются после завершения работы интерпретатора. Настрой
    ки в переменной окружения PYTHONPATH и в файлах .pth располагаются в самой операционной системе, а не в работающей программе, и пото
    му они имеют более глобальный характер: они воспринимаются всеми программами, которые запускаются на вашей машине, и продолжают существовать по завершении программы.
    Расширение import as
    Обе инструкции, import и from, были расширены так, чтобы позволить дать модулю в вашем сценарии другое имя. Следующая инструкция import
    :
    import longmodulename as name эквивалентна инструкциям:
    import longmodulename name = longmodulename del longmodulename # Не сохранять оригинальное имя
    После выполнения такой инструкции import для ссылки на модуль можно (и фактически необходимо) использовать имя, указанное после ключевого слова as. Точно такое же расширение имеется и у инструк
    ции from, где оно позволяет изменять имена, импортируемые из файла:
    from module import longname as name
    Это расширение обычно используется с целью создать короткие сино
    нимы для длинных имен и избежать конфликтов с именами, уже ис
    пользуемыми в сценарии, которые в противном случае были бы просто перезаписаны инструкцией импортирования. Кроме того, это расши
    рение может пригодиться с целью создания коротких и простых имен для длинных путей, состоящих из цепочки каталогов, при импортиро
    вании пакетов, которое описывалось в главе 20.
    Синтаксис относительного импорта
    В версии Python 2.5 была изменена семантика пути поиска в некото
    рых инструкциях from, когда они применяются к пакетам модулей, ко
    торые мы рассматривали в предыдущей главе. Некоторые аспекты это
    го изменения не будут очевидны до выхода более поздних версий Py
    thon (в настоящее время их включение запланировано для версий 2.7
    и 3.0), однако некоторые из них доступны уже сегодня.
    Говоря в двух словах, инструкции from теперь могут использовать точ
    ки («.»), чтобы указать, что поиск модулей в первую очередь должен производиться в том же самом пакете (эта особенность известна также как относительный импорт внутри пакета), и только потом может

    540
    Глава 21. Дополнительные возможности модулей выполняться гдето в другом месте, в пути поиска импортируемых мо
    дулей (эта особенность называется абсолютным импортом). То есть:

    На сегодняшний день можно использовать точки, чтобы указать,
    что импорт должен производиться относительно вмещающего па
    кета – при таком способе импортирования предпочтение будет отда
    ваться модулям, расположенным внутри пакета, а не одноименным модулям, находящимся гдето в пути поиска, в sys.path.

    Обычная операция импортирования в программном коде пакета
    (без точек) в настоящее время по умолчанию выполняется в поряд
    ке «сначала поиск относительно пакета, потом – абсолютный по
    иск». Однако в будущем интерпретатор будет по умолчанию ис
    пользовать абсолютный импорт – при отсутствии точек операции импортирования будут пропускать вмещающий пакет и искать им
    портируемые модули в пути поиска sys.path.
    Например, в настоящее время инструкция:
    from .spam import name означает: «из модуля с именем spam, расположенного в том же пакете,
    что и сама инструкция, импортировать переменную name». Похожая инструкция без начальной точки по умолчанию также будет использо
    вать порядок поиска «сначала относительно пакета, а затем – абсолют
    ный поиск», если только в импортирующий файл не будет включена следующая инструкция:
    from __future__ import absolute_import # До выхода версии 2.7?
    Если эта инструкция присутствует, она включает использование абсо
    лютного пути поиска, которое станет поведением по умолчанию в бу
    дущем. В результате этого все операции импортирования без дополни
    тельных точек будут пропускать компоненты в том же пакете и произ
    водить поиск по абсолютному пути, хранящемуся в списке sys.path.
    Например, когда абсолютный импорт включен таким способом, сле
    дующая инструкция всегда будет находить не модуль string в текущем пакете, а одноименный модуль в стандартной библиотеке:
    import string # Всегда будет находить версию модуля в стандартной библиотеке
    Без инструкции from __future__ всегда будет импортироваться модуль string
    , если он присутствует в пакете. Чтобы получить то же самое по
    ведение в будущем, когда по умолчанию будет выполняться абсолют
    ный импорт, для выполнения относительного импорта можно будет использовать следующую форму инструкции (которая работает и в на
    стоящее время):
    from . import string # Сначала поиск производится внутри пакета
    Обратите внимание: ведущий символ точки может использоваться только в инструкции from, в инструкции import он недопустим. Инст
    рукция import modname в настоящее время попрежнему выполняет от

    Синтаксис относительного импорта
    541
    носительный импорт, но в Python 2.7 она будет выполнять абсолют
    ный импорт.
    Возможны также и другие варианты точечной нотации для ссылки на модули в пакете. Допустим, что имеется пакет mypkg, тогда следующие альтернативные варианты импортирования внутри этого пакета будут работать так, как описывается:
    from .string import name1, name2 # Импорт имен из mypkg.string
    from . import string # Импорт mypkg.string
    from .. import string # Импорт string из родительского каталога
    Чтобы лучше понять эти последние формы инструкций, необходимо разобраться с обоснованием этого грядущего изменения.
    Зачем необходим относительный импорт
    Эта возможность предназначена, чтобы дать сценариям возможность ликвидировать возникающие неоднозначности, которые могут возни
    кать, когда в разных местах в пути поиска присутствует несколько од
    ноименных модулей. Рассмотрим следующий каталог пакета:
    mypkg\
    __init__.py main.py string.py
    Это каталог пакета с именем mypkg, содержащий модули mypkg.main и mypkg.string. Теперь предположим, что модуль main пытается импор
    тировать модуль с именем string. В Python 2.4 и в более ранних верси
    ях интерпретатор будет сначала искать модуль в каталоге mypkg, вы
    полняя относительный импорт. Он найдет и импортирует файл
    string.py
    , находящийся в этом каталоге, и присвоит его имени string в пространстве имен модуля mypkg.main.
    Однако может так получиться, что этой инструкцией предполагалось импортировать модуль string из стандартной библиотеки языка Py
    thon. К сожалению, в этих версиях Python нет достаточно простого способа проигнорировать модуль mypkg.string и импортировать модуль string из стандартной библиотеки, расположенной в пути поиска мо
    дулей правее. Мы не можем зависеть от структуры каталогов пакета,
    описанных выше стандартной библиотеки, присутствующей на любом компьютере.
    Другими словами, инструкции импортирования в пакетах могут быть неоднозначными – внутри пакета может быть непонятно, какой мо
    дуль пытается импортировать инструкция import spam, – внутри паке
    та или за его пределами. Если говорить более точно, локальный мо
    дуль или пакет могут сделать невозможным импорт другого модуля,
    присутствующего в пути поиска sys.path, преднамеренно или нет.
    На практике пользователи Python могут избегать использовать имена модулей стандартной библиотеки для своих модулей (если вам требует

    542
    Глава 21. Дополнительные возможности модулей ся стандартный модуль string, не называйте свой модуль этим именем).
    Но это не поможет, если пакет делает недоступным стандартный модуль случайно. Кроме того, с течением времени в стандартную библиотеку
    Python могут добавляться новые модули – с теми же именами, которые присвоены вашим уже существующим модулям. Программный код, ис
    пользующий особенности относительного импорта, сложнее понять, по
    тому что бывает трудно выяснить, какой модуль импортируется. Гораз
    до лучше, если решение явно описывается в программном коде.
    В Python 2.5 мы можем управлять поведением операций импорта, вы
    нуждая их использовать абсолютный режим импортирования инст
    рукцией from __future__, которая была описана ранее. Учтите, что ре
    жим абсолютного импортирования будет использоваться по умолча
    нию в будущих версиях (планируется ввести его в Python 2.7). Когда режим абсолютного импортирования будет включен, следующая инст
    рукция в нашем примере файла mypkg\main.py всегда будет находить версию модуля string из стандартной библиотеки благодаря абсолют
    ному поиску:
    import string # Импорт модуля string из стандартной библиотеки
    Вы должны уже сейчас привыкать к использованию абсолютного ре
    жима импорта, чтобы быть готовыми, когда изменения вступят в си
    лу. Таким образом, если вы действительно хотите импортировать мо
    дуль из своего пакета, то, чтобы сделать это явным и абсолютным, вы должны начать писать инструкции, подобные этой (mypkg будет най
    ден в режиме абсолютного поиска по sys.path):
    from mypkg import string # Импортирует mypkg.string (по абсолютному пути)
    Режим относительного импорта попрежнему остается доступным –
    при использовании точки в инструкции from:
    from . import string # Импортирует mypkg.string (по относительному пути)
    Данная форма инструкции импортирует модуль string относительно текущего пакета и является примерным эквивалентом абсолютной формы из предыдущего примера (поиск в каталоге пакета автоматиче
    ски выполняется в первую очередь).
    С помощью относительного синтаксиса можно также копировать за
    данные имена из модуля:
    from .string import name1, name2 # Импортирует имена из mypkg.string
    Эта инструкция также ссылается на модуль string относительно теку
    щего пакета. Если поместить эту инструкцию в модуль mypkg.main, на
    пример, она будет импортировать имена name1 и name2 из модуля myp
    kg.string
    . Дополнительная начальная точка предписывает выполнить относительный импорт, начиная с родительского каталога текущего пакета. Например, инструкция:
    from .. import spam # Импортирует модуль одного уровня с пакетом mypkg

    Концепции проектирования модулей
    1   ...   61   62   63   64   65   66   67   68   ...   98


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