Марк Лутц - Изучаем Python, Четвертое издание (1184811), страница 27
Текст из файла (страница 27)
Этот модуль сам также используетэти переменные в инструкции print, в чем можно убедиться, если запуститьэтот модуль как файл верхнего уровня:% python threenames.pydead parrot sketchКак обычно, программный код этого модуля выполняется всего один раз, приимпортировании (с помощью инструкции import или from). Клиенты, использующие инструкцию import, получают модуль со всеми его атрибутами, а клиенты, использующие инструкцию from, получают копии имен из этого модуля:% python>>> import threenamesdead parrot sketch>>>>>> threenames.b, threenames.c(‘parrot’, ‘sketch’)1# Загрузить модуль целикомОбратите внимание: в обеих инструкциях, import и from, имя модуля myfile указывается без расширения .py.
Как вы узнаете в пятой части книги, когда интерпретаторPython выполняет поиск файлов модулей, он знает, что к имени модуля необходимодобавить расширение. Не забывайте, что расширение обязательно должно указываться при вызове файла в системной командной оболочке и опускаться в инструкциях import.Импортирование и перезагрузка модулей99>>>>>> from threenames import a, b, c # Скопировать несколько имен>>> b, c(‘parrot’, ‘sketch’)Результаты здесь выводятся в круглых скобках, потому что в действительности они являются кортежами (разновидность объектов, которая описываетсяв следующей части книги). Пока вы можете спокойно игнорировать эту особенность.Как только вы начнете создавать модули, содержащие несколько имен, какв данном случае, вам наверняка пригодится встроенная функция dir.
Она может использоваться для получения списка имен, доступных внутри модуля.Следующая инструкция возвращает список строк (мы начнем знакомиться сосписками в следующей главе):>>> dir(threenames)[‘__builtins__’, ‘__doc__’, ‘__file__’, ‘__name__’, ‘a’, ‘b’, ‘c’]Такой результат получается при вызове функции в Python 3.0 и 2.6; в болееранних версиях количество возвращаемых имен может быть меньше. При вызове функции dir передается имя импортированного модуля в круглых скобках, как показано выше, а возвращает она список всех атрибутов, определенных внутри модуля. Некоторые возвращаемые имена, которые начинаютсяи завершаются двумя символами подчеркивания, присутствуют всегда; этивстроенные имена определяются самим интерпретатором Python и имеют длянего особый смысл.
Имена переменных, которые определяются нашими инструкциями присваивания, – a, b и c – выводятся в конце списка, получаемогоот функции dir.Модули и пространства именИмпортирование модулей – это один из способов запуска программного кодав файлах, но, помимо этого, и это будет рассмотрено в книге позже, модули являются также самой крупной структурной единицей в программах на языкеPython.Вообще программы на языке Python состоят из множества файлов модулей,связанных между собой инструкциями import. Каждый файл модуля – этосамостоятельный пакет переменных, или пространство имен. Один модульне сможет увидеть переменные, определенные в другом модуле, если явно неимпортирует его. Модули позволяют уменьшить вероятность конфликтовимен в программном коде – так как каждый файл является самостоятельнымпространством имен, имена в одном файле не вступают в конфликт с именамив другом файле, даже если они одинаковые.Как можно понять, модули – одно из ухищрений, которые используются в языке Python для упаковки переменных в категории, чтобы избежать конфликтовимен.
Далее мы еще будем обсуждать модули и другие конструкции образования пространств имен (включая классы и функции). А пока будем использовать модули в качестве средства многократного использования программногокода, позволяющего не вводить его повторно с клавиатуры.100Глава 3. Как пользователь запускает программыimport или from: необходимо отметить, что инструкция from в некотором смысле стирает границы пространств имен между модулями, потому что она копирует переменные из одного файлав другой.
Это может вызывать затирание переменных в импортирующем файле одноименными переменными в импортируемом файле (при этом никаких предупреждений выводиться небудет). По сути, эта инструкция выполняет разрушительноеобъединение пространств имен, по крайней мере, в терминах копируемых переменных.По этой причине многие рекомендуют использовать инструкцию import вместо from. Я не буду вдаваться в глубокомысленныерассуждения, однако отмечу, что инструкция from не только короче, но и подразумеваемая проблема редко возникает на практике. Обратите внимание, что инструкция from позволяет явноуказывать перечень импортируемых имен, и пока вы помните,что им будут присвоены значения, эта операция не более опасна, чем обычная инструкция присваивания, – еще одна возможность, которая наверняка будет использоваться вами!import и reload, примечания к использованиюЗачастую, узнав о возможности запуска файлов с помощью import и reload, начинающие разработчики концентрируют все свое внимание на этом способеи забывают о других возможностях запуска, позволяющих запускать всегдасамую свежую версию программного кода (например, щелчок мышью на ярлыке, пункты меню в IDLE и системная командная строка).
К тому же, такойподход может быстро привести к появлению ошибок – вам придется помнить,импортировали ли вы тот или иной модуль, чтобы иметь возможность перезагрузить его; вам нужно будет помнить о необходимости использовать круглыескобки при вызове функции reload (только для нее) и не забывать использоватьее, чтобы запустить самую последнюю версию модуля. Более того, операцияперезагрузки не является транзитивной – перезагружается только модуль,указанный в вызове функции reload, но не перезагружаются модули, которыеон импортирует, поэтому может возникнуть потребность перезагрузить несколько файлов.Из-за этих сложностей (и некоторых других, с которыми мы еще столкнемсяпозднее) пока лучше избегать пользоваться операциями импорта и перезагрузки.
Пункт меню Run (Запустить) → Run Module (Запустить модуль) в IDLE (описывается в следующем разделе), например, предоставляет более простой способзапуска файлов, менее подверженный ошибкам. Системная командная строкапредлагает похожие удобства. Вам не придется выполнять перезагрузку прииспользовании этих приемов.Следует добавить, что в случае использования необычных способов применения модулей, отличных от тех, которые к этому моменту описаны в книге, выможете столкнуться с некоторыми неприятностями.
Например, если вам необходимо импортировать файл модуля, который хранится в каталоге, отличномот того, в котором вы работаете, вам придется перейти к главе 21, где вы узнаете о пути поиска модулей.Запуск модулей с помощью функции exec 101А пока, чтобы избежать осложнений, храните все импортируемые файлы модулей в рабочем каталоге.1Следует также отметить, что операции импортирования и перезагрузки стали популярной методикой тестирования классов, и вполне возможно, что вамтакже понравится этот подход. Но если начнут возникать сложности – остановитесь!Запуск модулей с помощью функции execВ�����������������������������������������������������������������������действительности����������������������������������������������������������������������������������������������������������������������������существует������������������������������������������������������������������������������������������������еще���������������������������������������������������������������������������������несколько�������������������������������������������������������������������способов������������������������������������������������выполнить�����������������������������программ���������ный�������������������������������������������������������������������������������������������������������������������������������������код���������������������������������������������������������������, �������������������������������������������������������������хранящийся�����������������������������������������������������������������������������������������������������в������������������������������������������������� ������������������������������������������������файлах�����������������������������������������������������������������������������������модулей����������������������������������.
��������������������������������Например, вызов встроенной функции exec(open(‘module.py’).read()) – это еще один способ выполнять файлы изинтерактивной оболочки, фактически не импортируя модуль. Каждый последующий вызов exec будет выполнять текущую версию файла и ликвидирует необходимость позднее выполнять перезагрузку модуля (возьмем опятьсценарий script1.py в том виде, в каком мы оставили его после перезагрузкив предыдущем разделе):C:\misc> c:\python30\python>>> exec(open(‘script1.py’).read())win3265536Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!...изменим script1.py в текстовом редакторе...>>> exec(open(‘script1.py’).read())win324294967296Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!Вызов функции exec производит эффект, похожий на вызов инструкции import,но при этом он не импортирует модуль – по умолчанию всякий раз, когда вызывается функция call, она выполняет файл заново, как если бы он был вставленв месте вызова функции exec.
По этой причине при использовании функцииexec не требуется перезагружать модуль после внесения в него изменений – онане следует обычной логике импортирования.Однако, так как вызов exec по своему действию напоминает простую вставкупрограммного кода модуля на его место, подобно инструкции from, упоминавшейся выше, он может без предупреждения затереть существующие переменные. Например, в нашем сценарии script1.py выполняется присваивание значе-1Для тех, кто сгорает от любопытства, скажу, что интерпретатор Python выполняетпоиск импортируемых модулей во всех каталогах, перечисленных в переменной sys.path, – в списке имен каталогов, определенном в модуле sys, который инициализируется значением переменной окружения PYTHONPATH, и в наборе стандартных именкаталогов. Если возникает потребность импортировать модули из других каталогов,отличных от того, в котором вы работаете, они должны быть перечислены в переменной PYTHONPATH.
За дополнительной информацией обращайтесь к главе 21.102Глава 3. Как пользователь запускает программыния переменной x. Если это имя уже используется к моменту вызова функцииexec, значение переменной с этим именем будет затерто:>>> x = 999>>> exec(open(‘script1.py’).read()) # Код выполняется в этом же# пространстве имен...тот же самый вывод...>>> x # Присваивание в модуле затерло прежнее значение‘Spam!’Инструкция import, напротив, выполняет файл только один раз за все времявыполнения программы и создает отдельное пространство имен модуля, поэтому подобные операции присваивания не приводят к затиранию значений переменных в импортирующем программном коде.