Лутц М. - Изучаем Python (1077325), страница 104
Текст из файла (страница 104)
Реализация служб или данных для совместного пользования С функциональной точки зрения модули могут также использоваться для реализации компонентов, используемых системой, вследствие чего требуется только одна копия такого компонента. Например, если необходим глобальный объект, который используется более чем одной функцией или модулем, можно написать его в виде модуля, который затем может импортироваться множеством клиентов. Архитектура программы на языке РутЬоп 487 Однако, чтобы понять действительную роль модулей в системе РуаЬоп, нам необходимо отступить на шаг назад и исследовать общую структуру программы на языке РутЬоп.
Архитектура программы на языке РуФоп До сих пор в этой книге я избегал сложностей в описаниях программ на языке Ру(Ьоп. Обычно программы состоят более чем из одного файла — любые программы, за исключением самых простых сценариев, состоят из нескольких файлов. Даже если вам удастся поместить всю логику в один файл, вы почти наверняка будете использовать сторонние модули, которые уже кем-то были написаны.
В этом разделе дается введение в общую архитектуру программ на языке РуаЬоп — способ, которым программа делится на коллекцию файлов с исходными текстами (то есть модулей) и увязывается в единое целое. Кроме того, мы попутно рассмотрим основные концепции модулей в языке Ру(Ьоп, процедуру импортирования и атрибуты объектов. Как организована программа Как правило, программа на языке Ру$Ьоп состоит из множества текстовых файлов, содержащих инструкции. Программа организована как один главньгй файл, к которому могут подключаться дополнительные файлы, известные как модули.
Главный файл определяет, как будет двигаться основной поток выполнения программы, — это тот файл, который необходимо запустить, чтобы начать работу приложения. Файлы модулей — это библиотеки инструментальных средств, где содержатся компоненты, используемые главным файлом (и, возможно, где-то еще). Главный файл использует инструменты, определенные в файлах модулей, а модули используют инструменты, определенные в других модулях. Обычно файлы модулей ничего не делают, если попытаться запустить их отдельно, — в них определяются инструментальные средства, используемые в других файлах.
Чтобы получить доступ к определенным в модуле инструментам, именующимся атрибутами модуля (имеиа переменных, связанные с такими объектами, как функции), в языке РутЬоп необходимо и илортироваоть этот модуль. То есть мы импортируем модули и получаем доступ к их атрибутам, что дает нам возможность использовать их функциональные возможности. Импортирование и атрибуты Давайте сделаем наше обсуждение более конкретным. На рис.
18.1 схематически изображена структура программы на языке РутЬоп, состоящей из трех файлов: а.ру, Ь.ру и с.ру. Файл а.ру является главным файлом программы — это простой текстовый файл, состоящий из инст- 4ВВ Глава 18. Модули: общая картина рукций, который при запуске выполняется от начала и до конца. Файлы Ь.ру и с.ру — это модули, они также являются простыми текстовыми файлами, содержащими инструкции, но обычно они не запускаются как самостоятельные программы. Вместо этого они, как уже говорилось выше, обычно импортируются другими файлами, использующими инструментальные средства, определяемые в этих файлах. Например, предположим, что файл Ьру на рис.
18.1 определяет функцию с именем зрзв. Как мы уже знаем из четвертой части книги, чтобы определить функцию, которая затем сможет быть запущена за счет передачи ей нуля или более аргументов в круглых скобках, файл Ь.ру должен содержать инструкцию Сот: сег ерав(техт): рггк техт, 'зрав' Теперь предположим, что модуль а.ру использует функцию ерзв. Для этого он мог бы содержать следующие инструкции: 1врогт Ь Ь.ерав('девЬу') В первой строке здесь располагается инструкция Ьврсгт, дающая файлу а.ру доступ ко всему, что определено на верхнем уровне в файле Ь.ру.
Вкратце это означает следующее: «загрузить файл Ь.ру (если он еще не загружен) и предоставить доступ ко всем его атрибутам через имя модуля Ь». Инструкции 1врсгт (и, как вы узнаете далее, Гсов) загружают и запускают другие файлы на этапе времени выполнения. Рис. 1В.1. Архитектура программы на языке РутИоп. Программа — это система модулей. Она состоит иэ одного главного файла сценария Г который требуется запустить, чтобы начать работу программы) и нескольких модулей (импортируемгнх библиотек инструментальных средств). И сценарии, и модули — это текстов«не файлы, содержащие инструкции на язгнке РуГИоп, хотя инструкции в модулях обычно только создают объекты для последующего использования. Стандартная библиотека яэьгка Ругйоп представляет собой коллекцию модулей, готовых к использованию Архитектура программы на языке Ру(Ьоп В языке Ру(Ьоп невозможно обращаться к именам в других модулях, пока такие инструкции импорта не будут выполнены на этапе времени выполнения.
Основная задача этих инструкций состоит в том, чтобы связать имена в модуле — простые переменные — с объектами загруженных модулей. Фактически, имя модуля, используемое в инструкции парогт, во-первых, идентифицирует внешний файл и, во-вторых, становится именем переменной, которая будет представлять загруженный модуль. Объекты, определяемые модулем, также создаются во время выполнения, когда производится импорт модуля: инструкция (эрогт, в действительности, последовательно выполняет инструкции в указанном файле, чтобы воссоздать его содержимое.
Вторая инструкция в файле а.ру вызывает функцию враз, определенную в модуле Ь, используя форму записи атрибутов объекта, Запись Ь. ораз означает следующее: «извлечь значение имени зрав, расположенного в объекте Ь». В нашем примере — это вызываемая функция, поэтому далее ей передается строка в круглых скобках ( 'роэЬу' ). Если вы создадите эти файлы, сохраните их и запустите файл а.ру, то будут выведены слова «дптЬу врат». Вы увидите, что повсюду в сценариях на языке Ру(Ьоп используется нотация оЬ)ест.
аттгтооте — большинство объектов обладают атрибутами, доступ к которым можно получить с помощью оператора «. ». Некоторые атрибуты — имена вызываемых функций, а другие — простые значения, которые представляют свойства объекта (например, имя персоны), Импорт — широко используемое понятие в языке РутЬоп. Любой файл может импортировать функциональные возможности из любого другого файла.
Например, файл а.ру может импортировать файл Ь.ру, чтобы иметь возможность вызывать его функцию, при этом файл Ь.ру может в свою очередь импортировать файл с.ру, чтобы получить доступ к другим функциональным возможностям, определенным в нем. Цепочка импортирования может уходить так глубоко, как это потребуется: в этом примере модуль а может импортировать модуль Ь, который импортирует модуль с, который в свою очередь может еще раз импортировать модуль Ь, и т. д. Помимо самой крупной единицы в организационной структуре программы модули (и пакеты модулей, которые описываются в главе 20) также играют роль самой крупной единицы программного кода, доступного для повторного использования.
Оформив программные компоненты в виде файлов модулей, вы сможете использовать их не только в оригинальной программе, но и в любых других программах, которые вам придется писать. Например, если после написания программы, структура которой изображена на рис. 18.1, вдруг обнаружится, что функция Ь. зраэ является универсальным инструментом, мы сможем использовать ее в других программах.
Все, что нам потребуется,— это импортировать файл Ь.ру из файлов другой программы. 490 Глава 18. Модули: общая картина Модули стандартной библиотеки Обратите внимание на правую часть рис. 18.1. Некоторые из модулей, которые будут импортироваться вашими программами, входят непосредственно в состав языка РуФЬоп, и вам не придется писать их. Интерпретатор Ру1Ьоп поставляется с обширной коллекцией дополнительных модулей, которая известна как стандартнал библиотека.
Эта коллекция насчитывает порядка 200 крупных модулей и содержит платформонезависимую поддержку распространенных задач программирования: интерфейсы операционных систем, организацию хранилищ объектов, поиск по шаблону, сетевые взаимодействия, создание графического интерфейса и многих других. Ни один из этих инструментов не является непосредственной частью языка Ру1Ьоп, но вы можете использовать их, импортируя соответствующие модули.
Так как это модули стандартной библиотеки, можно быть уверенным, что они будут доступны и будут работать переносимым образом на большинстве платформ, на которых работает интерпретатор РуФЬоп. В примерах этой книги вы увидите несколько модулей стандартной библиотеки в действии, но за полной информацией вам следует обратиться к справочным руководствам по стандартной библиотеке языка РуФоп, которые можно найти в инсталляции Ру1Ьоп (в П)ЬЕ или в меню кнопки Пуск (5(ат() в операционной системе ттГ)пдошв) или в Интернете, по адресу: )тт(р://шшш.ру(Иоп.ого. При таком большом количестве модулей это действительно единственный способ получить представление о том, какие инструментальные средства имеются в наличии. Кроме этого, описание библиотеки инструментов РуФЬоп можно найти в некоторых книгах, посвященных прикладному программированию, таких как «Ргоягаппп1пя РуФЬопя, но, в отличие от книг, руководства распространяются бесплатно, их можно просматривать в любом веб-броузере (поскольку они распространяются в формате НТМ1) и к тому же они обновляются с выходом каждой новой версии РуФЬоп.
Как работает импорт В предыдущем разделе говорилось об импортировании модулей, но никак не объяснялось, что происходит во время импорта. Так как в языке Ру1Ьоп инструкции импортирования составляют основу структуры программы, здесь мы подробнее рассмотрим этот вопрос, чтобы сделать представление о процессе импорта менее абстрактным. Некоторые программисты на языке С любят сравнивать инструкцию 1вро гт в языке Ру1Ьоп с инструкцией Фтлс1зсе, но они в корне неправы— импортирование в языке РуФЬоп — это не просто включение текста одного файла в другой.
Это самые настоящие операции времени выполнения, которые выполняют следующие действия, когда программа впервые импортирует заданный файл: 491 Как работает импорт 1. Отьгскивают файл модуля. 2. Компилируют в байт-код (если это необходимо). 3. Залускаюлт программный код модуля, чтобы создать объекты, которые он определяет.
Чтобы лучше понять, как протекает импорт модулей, мы исследуем все эти действия по порядку. Примите во внимание, что все три действия выполняются, только когда модуль впервые импортируется во время выполнения программы — все последующие операции импорта того же модуля пропускают эти действия и просто выбирают уже находящийся в памяти объект модуля. 1. Поиск Прежде всего, интерпретатор должен определить местонахождение файла модуля, указанного в инструкции (зрогт. Обратите внимание, что имена файлов в инструкции тнрогт в примерах из предыдущих разделов указаны без расширения .ру и без пути к каталогу: вместо записи в виде, например, 1арогт с: т,б(гтттЬ. ру инструкция записывается просто— (арогт Ь.