Лутц М. - Изучаем Python (1077325), страница 115
Текст из файла (страница 115)
Однако при такой реализации имеется одна проблема — результаты самопроверки будут выводиться на экран всякий раз, когда этот файл будет импортироваться для использования другим файлом, но тогда это становится невежливым по отношению к пользователю! Чтобы исправить положение, можно обернуть проверочные вызовы функции в условную инструкцию, проверяющую атрибут паве так, чтобы они выполнялись, только когда файл запускается как самостоятельная программа, а не во время импорта: рггп! '1 аа ', паве оег а пвах((ев1, *агдв); гев = агдв[0) (ог агд зп агре[1;): з( гев((агд, гев): гев = агд Ге!ого гва Оег 1евв1Пап(х, у): ге(огп х < у Ое( дг1г1Пап(х, у): ге1огп х > у паве == ' ваго ргзп( азовах(1евв1оап, 4, 2, 1, 5. 6, 3) Ф Код самопроверке рмп( вгпаах(дг1г1пап, 4, 2, 1, 5, б, 3) Здесь в самом начале добавлена инструкция вывода значения атрибута паве, чтобы проверить его визуально.
Интерпретатор Ру$)зоп создает эту переменную и присваивает ей значение во время загрузки файла. Когда файл запускается как самостоятельная программа, этому имени присваивается значение ' ва! п ', поэтому в данном случае происходит автоматическое выполнение кода самопроверки: % рувяоп а!п.ру 1 ав: ваза 1 6 Однако, когда файл импортируется, значение атрибута паве уже не равно ' вазп ', поэтому необходимо явно вызвать функцию, чтобы запустить ее: »> !враге а!п 538 Глава 21. Дополнительные возможности модулей 1 аа В1п »> 51П.В1пвах(51п. 1еввтпап, 'в', 'р', 'а', 'в') 'а' Неважно, будет ли использоваться этот прием для нужд тестирования, главный результат — что наш программный код может использоваться и как библиотека инструментов, и как самостоятельная программа. Изменение пути поиска модулей В главе 18 мы узнали, что путь поиска модулей — это список каталогов, и что этот список можно дополнить с помощью переменной окружения РУТНОНРАТН и файлов .р(ГГ.
Но я пока еще не показывал, как сами программы на языке Ру1)1оп могут изменять путь поиска, изменяя встроенный список с именем вув. Ратп (атрибут ратп встроенного модуля вув). Список вув. Ра(П инициализируется во время запуска программы, однако после этого допускается удалять, добавлять и изменять компоненты списка по своему усмотрению: »> 1ВРОГт 5у5 »> вув.рать [ , 'О, 11ррзесэ-рагт(а1~1ехаар155', 'с:'хтрутпоп25', ...далее опуаено . ) »> вув.рата.вррепб('с:'115оогсеб1г') й дополнение пути поиска иодулей »> 1арогт втг1пр й Новей каталог будет унастеовать й в поиске Как только будут внесены изменения, они будут воздействовать на все последующие инструкции импорта, выполняемые в программе, так как все инструкции во всех файлах программы используют один и тот же общий список вув.
Ратп. Этот список может изменяться произвольным образом: »> вув.рата = [г'б:'ттевр') Ф Иэиениет путь поиска ходулей »> вув.рать.аррепб('с:'111рзе'1)ехавр155') Ф только длл этой програииь »> вув.рать [ б; 11(еар', 'с;'тт1рзе>,>,ехаар1ев') »> 1ВРОГ1 51Г1пр тгасеьасх (аовт Гесепт саи 1а51): р11е Г<втб(п>", 11пе 1, тп и Харог(Еггог: Но вобо!е пааво втг(пр Таким образом, этот прием может использоваться для динамической настройки пути поиска внутри программ на языке Ру()гоп. Однако будьте внимательны: если убрать из пути критически важный каталог, можно потерять доступ к критически важным утилитам.
В предыдущем примере, например, был потерян доступ к модулю в( Г1ПС, потому что из пути был удален исходный каталог библиотеки. Кроме того, не забывайте, что такие изменения списка вув. Ратп действуют только в рамках интерактивного сеанса или внутри программы (тех- Расширение ипрог1 аа нически — в рамках процесса), где были выполнены эти изменения,— они не сохраняются после завершения работы интерпретатора.
Настройки в переменной окружения РУТНОИРАТН и в файлах .ргй располагаются всамой операционной системе, а не в работающей программе, и потому они имеют более глобальный характер: они воспринимаются всеми программами, которые запускаются на вашей машине, и продолжают существовать по завершении программы. Расширение ипрог1 ая Обе инструкции, 1врогг и 1 гон, были расширены так, чтобы позволить дать модулю в вашем сценарии другое имя.
Следующая инструкция 1врогы гврогг 1опдвсс»1апаве аа паве эквивалентна инструкциям: 1врог1 1опдвоап1апава паве = 1опдвоап1епава Са1 1опдвоап!епаве Ф Не сохранят» оригинал»ное имп После выполнения такой инструкции (врогг для ссылки на модуль можно (и фактически необходимо) использовать имя, указанное после ключевого слова аа. Точно такое же расширение имеется и у инструкции Т гов, где оно позволяет изменять имена, импортируемые из файла: Ггов воа»1е 1впог1 1опдпаве аа паве Это расширение обычно используется с целью создать короткие синонимы для длинных имен и избежать конфликтов с именами, уже используемыми в сценарии, которые в противном случае были бы просто перезаписаны инструкцией импортирования.
Кроме того, это расширение может пригодиться с целью создания коротких и простых имен для длинных путей, состоящих из цепочки каталогов, при импортировании пакетов, которое описывалось в главе 20, Синтаксис относительного импорта В версии Ру$Ьоп 2.5 была изменена семантика пути поиска в некоторых инструкциях Тгов, когда они применяются к пакетам модулей, которые мы рассматривали в предыдущей главе. Некоторые аспекты этого изменения не будут очевидны до выхода более поздних версий Ру(Ьоп (в настоящее время их включение запланировано для версий 2.7 и 3.0), однако некоторые из них доступны уже сегодня. Говоря в двух словах, инструкции Тгов теперь могут использовать точки («. »), чтобы указать, что поиск модулей в первую очередь должен производиться в том же самом пакете (эта особенность известна также как относительный импорт внутри пакета), и только потом может 540 Глава 21.
Дополнительные возможности модулей выполняться где-то в другом месте, в пути поиска импортируемых модулей (эта особенность называется абсолютным им нортом). То есть: ° На сегодняшний день можно использовать точки, чтобы указать, что импорт должен производиться относительно вмещающего пакета — при таком способе импортирования предпочтение будет отдаваться модулям, расположенным внутри пакета, а не одноименным модулям, находящимся где-то в пути поиска, в зуз, раСЛ. ° Обычная операция импортирования в программном коде пакета (без точек) в настоящее время по умолчанию выполняется в порядке «сначала поиск относительно пакета, потом — абсолютный поиск».
Однако в будущем интерпретатор будет по умолчанию использовать абсолютный импорт — при отсутствии точек операции импортирования будут пропускать вмещающий пакет и искать импортируемые модули в пути поиска зуз. расо. Например, в настоящее время инструкция: Ггаа враа зарогт паве означает: «из модуля с именем зраа, расположенного в том же пакете, что и сама инструкция, импортировать переменную паве». Похожая инструкция без начальной точки по умолчанию также будет использовать порядок поиска «сначала относительно пакета, а затем — абсолютный поиске, если только в импортирующий файл не будет включена следующая инструкция: Ггоа Готоге аарогт аово1нсе аарогт В До виходв версии 2.г« Если эта инструкция присутствует, она включает использование абсолютного пути поиска, которое станет поведением по умолчанию в будущем. В результате этого все операции импортирования без дополнительных точек будут пропускать компоненты в том же пакете и производить поиск по абсолютному пути, хранящемуся в списке еуе.
ра1п. Например, когда абсолютный импорт включен таким способом, следующая инструкция всегда будет находить не модуль з1г!пд в текущем пакете, а одноименный модуль в стандартной библиотеке: гарогт зтгтпд в Всегда будет находить версию иодупя в ствндвртиой библиотеке Без инструкции Ггоа Гасо ге всегда будет импортироваться модуль зсг1пд, если он присутствует в пакете. Чтобы получить то же самое поведение в будущем, когда по умолчанию будет выполняться абсолютный импорт, для выполнения относительного импорта можно будет использовать следующую форму инструкции (которая работает и в настоящее время): ггоа . 1арогт зтгтпд в Внаивпа поиск производится внутри пакета Обратите внимание: ведущий символ точки может использоваться только в инструкции Ггоа, в инструкции зарогс он недопустим. Инструкция 1арог1 аобпаае в настоящее время по-прежнему выполняет от- Синтаксис относительного импорта носительный импорт, но в Ру11топ 2.7 она будет выполнять абсолютный импорт.
Возможны также и другие варианты точечной нотации для ссылки на модули в пакете. Допустим, что имеется пакет вурнд, тогда следующие альтернативные варианты импортирования внутри этого пакета будут работать так, как описывается: тгов .атг1пц тарогт паве1, паве2 а импорт имен из ауркд.зггтлд Ггов . 1арогт атг1пц а Импорт мурад,зсгтлд тгоа,, тарогт зтгтпд Ф Импорт зтгтпд из родительского каталога Чтобы лучше понять эти последние формы инструкций, необходимо разобраться с обоснованием этого грядущего изменения.
Зачем необходим относительный импорт Эта возможность предназначена, чтобы дать сценариям возможность ликвидировать возникающие неоднозначности, которые могут возникать, когда в разных местах в пути поиска присутствует несколько одноименных модулей. Рассмотрим следующий каталог пакета: ауркцу тптт .ру ва1п ру атгтпд.ру Это каталог пакета с именем ауркд, содержащий модули вуркд.ватп и ауркд. а1ыпд. Теперь предположим, что модуль ва1п пытается импортировать модуль с именем отгапд. В РуФоп 2.4 и в более ранних версиях интерпретатор будет сначала искать модуль в каталоге птурйИ, выполняя относительный импорт.