Саммерфилд - Программирование на Python 3 (1077331), страница 50
Текст из файла (страница 50)
Подобное переименование, в частности, удобно использовать при экспериментировании с различными реализациями одного и того же модуля. Например, допустим, что у нас имеется два модуля МуМози1ед и Муиоои1еВ, которые имеют один и тот же АР1 (Арр11- Модули и пакеты Ниже приводятся еще несколько вариантов использования инструк- ции!врогт: зврргт ЬЬ)ест ав ргеуеггвп паве фврогт об)вст), паувсГ2,,, ЬЬ)апта !враг! (оь)есг1, оь)ест2, пьзесгз, пь>пст«, пьуесг5, ЬЫесГВ) тврргт * Ггов тврогтаЫЬ Ггов тврьгтаЫе Ггпв ьярогтаЫе ОЬ1ВСГ6, тгрв !вррггаЫв Эти синтаксические конструкции могут приводить к конфликтам имен, поскольку они обеспечивают непосредственный доступ к импортируемым объектам (переменным, функциям, типам данных или модулям). Если для импортирования большого числа объектов необходимо использовать синтаксис (гов ...
1врогт, мы можем расположить инструкцию импорта в нескольких строках, либо экранируя каждый символ перевода строки, кроме последнего, либо заключая список имен объектов в круглые скобки, как показано в третьем примере. В последней синтаксической конструкции символ «*» Функция означает «импоРтиРовать все имена, котоРые не ЯвлЯют- а11 () ся частными». На практике зто означает, что будут им- стр.
гаа портированы все объекты из модуля за исключением тех, чьи имена начинаются с символа подчеркивания, либо, если в модуле определена глобальная переменная а11 со списком имен, будут импортированы все объекты, имена которых перечислены в переменной а11 Ниже приводятся несколько примеров использования инструкции заро г1: тврргт оз рг1пт(оз.рать.ьазвпавв(гт1впавв)) а безопасный доступ по полным я квалифицированным именам тврогт оз.рата ав рати ргшт(рать.ьазвпавв((11епавв)) я есть риск конфликта иман с модулем рати ггов ов 1врогт рать ргшт(рать.ьаввпавв((11впавв)) я есть риск конфликта имен с модулем рать тгов оз.рати тврогт Ьазвпавв ргьпт(ьазвпавв(111впавв)) я есть риск конфликта имен с модулем ьазвпавв са!!оп Ргоягаппп1пя 1пфег1асе — прикладной программный интерфейс); мы могли бы в программе записать инструкцию 1врог1 МуМобы1ед аа МуМозц1е, а позднее легко переключиться на использование 1вро гт Муцобы1еВ аа МуМосы1е.
Где должна находиться инструкция 1врогт"г Обычно все инструкции зврогт помещаются в начало файла.ру, после строки «вЬеЬапк» и после описания модуля. И, как уже говорилось в главе 1, мы рекомендуем сначала импортировать модули стандартной библиотеки, затем модули сторонних разработчиков и в последнюю очередь свои собственные модули.
Глава 5. Модули ггоа ов.рата терогт ° ргнп(пвеепаее(гт1епаее)) Ф есть риск множественнык конфликтов имен Синтаксис (гоге тэроггаЬ2е 1зрогГ * используется для импортирования всех объектов из модуля (или из всех модулей пакета) — это могут быть сотни имен. В случае Ггоа оа. раГП Гзрогг * будет импортировано почти 40 имен, включая имена г)1гпазе, ех1ега и ер111, которые, вполне вероятно, мы могли бы использовать в качестве имен для наших собственных переменных нли функций. Например, если записать инструкцию Ггов ое. раГП тгврогГ 41гпазе, мы получим удобную возможность вызывать функцию Отгпазе(), не указывая полное квалифицированное имя. Но если ниже в нашем программном коде будет встречена инструкция С(глазе = ".", то после ее выполнения ссылка на объект г)тгпаае будет указывать уже не на функцию Стгпаэе(), а на строку ".
". Поэтому, если мы попытаемся вызвать функцию отгпаее(), мы получим исключение ТуреЕггог, потому что теперь имя от глазе ссылается на строку, а не на вызываемый объект. Ввиду того, что синтаксис тзрогГ * потенциально опасен появлением конфликтов имен, некоторые коллективы разработчиков вырабатывают свои правила, устанавливающие, что в их разработках может использоваться только синтаксис 1зрогГ тэроггаа!е. Однако некоторые крупные пакеты, в частности библиотеки ОШ (ОгарЫса! Т)аег 1пфегТасе — графический интерфейс пользователя), нередко импортируются таким способом, потому что они включают огромное число функций и классов (собственных типов данных), для которых было бы слишком утомительно вводить вручную полные имена. Возникает естественный вопрос — как интерпретатор узнает, где искать импортируемые модули и пакеты? Встроенный модуль ауа имеет список с именем еуа, раГП, в котором хранится перечень каталогов, составляющих лугпь поиска Ругбоп.
Первый каталог в этом списке — это каталог, где находится сама программа, даже если она вызывается из другого каталога. Далее в списке находятся пути к каталогам из переменной окружения РУТНОНРАТН, если она определена. И в конце списка находятся пути к каталогам стандартной библиотеки языка Руф)топ— они определяются на этапе установки РуГЬоп. Я Когда модуль импортируется впервые, если он не является встроенным, интерпретатор пытается отыскать его поочередно в каждом из каталогов, перечисленных в списке еуа. раГП. Как следствие этого, если мы создаем модуль или программу, имя которого совпадает с именем библиотечного модуля, наш модуль будет найден первым, что неизбежно будет приводить к проблемам.
Чтобы избежать этого, никогда не создавайте программы или модули, имена которых совпадают с именами модулей или каталогов верхнего уровня в библиотеке, если только вы не пытаетесь подставить свою собственную реализацию и ваше переопределение преднамеренно. (Модулем верх- Модули и пакеты него уровня называется файл .ру, который находится в одном из каталогов, включенных в путь поиска Ру()топ, а не в каком-нибудь подкаталоге, вложенном в один из этих каталогов.) Например, в системе 'тот1пг(овгз в путь поиска Ру()топ обычно включается каталог с именем С:т РугйопЗО~й(Ь, поэтому на этой платформе мы не должны создавать модуль с именем ИЬ.ру, так же как модуль, имя которого совпадает с именем любого модуля из каталога С:ттРу(ЬопЗОт,ИЬ.
Один из способов быстро проверить, используется ли то или иное имя модуля, состоит в том, чтобы попытаться импортировать модуль. Сделать это можно в консоли, вызвав интерпретатор с ключом -с («ехесите соде» вЂ” выполнить программный код), за которым следует указать инструкцию тарогт. Например, если необходимо проверить, существует ли модуль с именем Еаатс ру (или каталог верхнего уровня Миа(с в пути поиска Ру()топ), можно ввести в консоли следующую команду: Оутпоо -г.
"1арогт моато" Если в ответ будет получено исключение 1эрогтЕггсг, можно быть уверенным, что модуль или каталог верхнего уровня с таким именем не используется; любой другой вывод (или его отсутствие) означает наличие такого имени. К сожалению, такой прием не дает полной гарантии, что впоследствии с этим именем не будет возникать никаких проблем, поскольку позднее мы можем установить пакет или модуль, созданный сторонним разработчиком, имеющий такое же имя, хотя на практике такая проблема возникает достаточно редко.
Например, если мы создадим модуль окру, он будет конфликтовать с библиотечным модулем оа. Но если мы создадим модуль рагй.ру, то никаких проблем возникать не будет, поскольку этот модуль пришлось бы импортировать как модуль рата, тогда как библиотечный модуль должен импортироваться как оа. рата. В этой книге имена файлов наших собственных модулей всегда будут начинаться с символа верхнего регистра; это позволит избежать конфликтов имен (по крайней мере в Пг(1Х), потому что имена файлов библиотечных модулей состоят исключительно из символов нижнего регистра. Программа может импортировать некоторые модули, которые в свою очередь импортируют другие модули, включая те, что уже были импортированы.
Это не является проблемой. Всякий раз, когда выполняется попытка импортировать модуль, интерпретатор Ру()топ сначала проверяет — не был ли импортирован требуемый модуль ранее. Если модуль еще не был импортирован, Ру()топ выполняет скомпилированный байт-код модуля, создавая тем самым переменные, функции и другие объекты модуля, после чего добавляет во внутреннюю структуру запись о том, что модуль был импортирован. При любых последующих попытках импортировать этот модуль интерпретатор будет обнаруживать, что модуль уже импортирован и не будет выполнять никаких действий. Глава 5.
Модули Когда интерпретатору требуется скомпилированный байт-код модуля, он генерирует его автоматически — этим РуФоп отличается от таких языков программирования, как дача, где компилирование в байт-код должно выполняться явно.
Сначала интерпретатор попытается отыскать файл, имя которого совпадает с именем файла, имеющего расширение .Ру, но имеющий расширение .руо — это оптимизированный байт-код скомпилированной версии модуля. Если файл с расширением .Руо не будет найден (или он более старый, чем файл с расширением .Ру), интерпретатор попытается отыскать одноименный файл с расширением .рус — это неоптимизированный байт-код скомпилированной версии модуля. Если интерпретатор обнаружит актуальную скомпилированную версию модуля, он загрузит ее; в противном случае РуФЬоп загрузит файл с расширением .ру и скомпилирует его в байт-код. В любом случае интерпретатор загрузит в память модуль в виде скомпилированного байт-кода.