Учебник Python 3.1. Учебник Python 3. Учебник Python 1 Материал из Викиучебника. Оглавление
Скачать 1.85 Mb.
|
Выполнение модулей в качестве сценариев Когда вы запускаете модуль Python в виде python fibo.py < параметры > то код в этом модуле будет исполнен в момент его импортирования, но значением __name__ будет строка "__main__" . Это значит, что добавляя следующий код в конец сценария: if __name__ == "__main__" : import sys fib( int ( sys .argv[ 1 ])) вы можете сделать возможным запуск файла и в качестве сценария, и в качестве импортируемого модуля. Это возможно, поскольку разбирающий командную строку код выполняется только при исполнении модуля как основного (main) файла: $ python fibo.py 50 1 1 2 3 5 8 13 21 34 Если модуль импортируется, код не будет выполнен: >>> import fibo >>> Такой приём часто используется, чтобы предоставить удобный пользовательский интерфейс к модулю или для тестирования (выполнение модуля в качестве сценария запускает набор тестов). Путь поиска модулей Если импортируется модуль с именем spam , интерпретатор ищет файл с именем spam.py в текущем каталоге, а затем в каталогах, указанных в переменной окружения PYTHONPATH . У неё такой же синтаксис, как и у переменной шелла PATH , которая, в свою очередь, является перечислением каталогов. Когда переменная PYTHONPATH не установлена, или файл не найден в описанных в ней местах, поиск продолжается по пути по умолчанию, зависящему от указанного при установке; на Unix это обычно .:/usr/local/lib/python. 43 Учебник Python 3.1: Материал из Викиучебника. В действительности поиск модулей производится в списке каталогов в переменной sys.path , которая обычно содержит: каталог, в котором находится сценарий на входе (или текущий каталог), PYTHONPATH и умолчанием для каталога, указанного при установке. Это позволяет программам на Python (если программист знает, что делает) изменять или подменять путь поиска модулей. Заметьте: поскольку каталог, содержащий запускаемый вами сценарий, также находится в пути поиска, важно, чтобы в нем не было сценариев с именем стандартного модуля. Иначе, когда этот модуль будет импортироваться, Python будет пытаться загрузить в виде модуля сам сценарий, что в большинстве случаев вызовет ошибку. Для более подробной информации обратитесь к разделу Стандартные модули „Скомпилированные“ файлы Python Интерпретатор Python применяет один важный приём для ускорения запуска программы: если в каталоге, где располагается файл с некоторым модулем spam.py, находится также файл spam.pyc, предполагается, что это уже скомпилированная в байт-код („byte- compiled“) версия модуля spam . В файле spam.pyc зафиксировано время изменения файлаspam.py версии, использовавшейся для создания spam.pyc. Если версии не совпадают — файл .pyc игнорируется. В обычном случае, вам не нужно ничего делать для создания файла spam.pyc. Каждый раз, когда spam.py успешно компилируется, предпринимается попытка записать скомпилированную версию в spam.pyc. Не считается ошибкой, если попытка неудачна: если по какой-либо причине файл не записан полностью, результирующий файл spam.pycбудет считаться некорректным и по этой причине в дальнейшем игнорироваться. Содержимое файла spam.pyc платформо-независимо, благодаря чему каталог модулей Python может использоваться параллельно машинами с различной архитектурой. Несколько советов экспертам: • Когда интерпретатор Python запускается с флагом -O, в файлах .pyo сохраняется сгенерированный оптимизированный код. На данный момент оптимизатор помогает не сильно — он лишь удаляет операторы assert . В случае использования - O оптимизируется весь байт-код (bytecode); файлы .pyc игнорируются, а файлы .py компилируются в оптимизированный байт-код. • Передача двух флагов -O интерпретатору Python (-OO) принуждает компилятор байт-кода выполнять оптимизации, в редких случаях результат выполнения которых оказывается некачественно функционирующей программой. На данный момент из байт-кода удаляются только строки __doc__ , в результате получаются более компактные файлы .pyo. Поскольку некоторые программы могут рассчитывать на их (строк) доступность, следует использовать эту возможность только в том случае, если вы знаете что делаете. • Программа сама по себе не работает хоть сколь-нибудь быстрее, будучи прочитанной из файла .pyc или .pyo, чем если бы она была прочитана из файла .py. Единственный процесс, оказывающийся более быстрым при использовании файлов .pyc или .pyo — это скорость их подгрузки. • Если сценарий запущен из командной строки, его байт-код никогда не будет записан в файл .pyc или .pyo. Таким образом, время запуска сценария может быть 44 Учебник Python 3.1: Материал из Викиучебника. уменьшено за счёт перемещения большей части его кода в модули или использования небольшого загрузочного сценария, импортирующего этот модуль. Кроме того, можно указывать файл.pyc или .pyo прямо в командной строке. • Можно иметь в наличии файл с именем spam.pyc (или spam.pyo, когда используется -O), не имея файла spam.py для того же модуля. Таким образом можно распространять библиотеки кода Python в том виде, из которого трудно восстановить исходный код. • Модуль compileall может создать файлы .pyc (или файлы .pyo, когда используется -O) для всех модулей в каталоге. Стандартные модули Python поставляется с библиотекой стандартных модулей, описанной в отдельном документе, Python Справочнике по библиотеке (далее — «Справочнику по библиотеке»). Некоторые модули встроены в интерпретатор. Они обеспечивают доступ к операциям, не входящим в ядро языка, и встроены для большей эффективности и предоставления доступа к основным средствам операционной системы, таким как системные вызовы (system calls). Набор таких модулей — выбор настройки, зависимый от используемой платформы. Например, модуль winreg предоставляется только на системах с Windows. Один конкретный модуль заслуживает большего внимания: модуль sys , встроенный в каждую версию интерпретатора Python. Переменные sys.ps1 и sys.ps2 определяют строки, использующиеся в качестве основного и вспомогательного приглашений: >>> import sys >>> sys .ps1 '>>> ' >>> sys .ps2 '... ' >>> sys .ps1 = "Вводите: " Вводите: ( 'Ох!' ) Ох ! Вводите: Эти две переменные определены только для интерактивного режима интерпретатора. Переменная sys.path представляет из себя список строк, определяющий путь поиска модулей интерпретатора. Она инициализируется значением пути по умолчанию, взятым из переменной окружения PYTHONPATH, или встроенным значением по умолчанию, если PYTHONPATH не установлен. Вы можете изменить её значение, используя стандартные операции со списками: >>> import sys >>> sys .path.append( '/ufs/guido/lib/python' ) Функция dir() Встроенная функция dir() используется для получения имён, определённых в модуле. Она возвращает отсортированный список строк: >>> import fibo , sys >>> dir (fibo) [ '__name__' , 'fib' , 'fib2' ] >>> dir ( sys ) [ '__displayhook__' , '__doc__' , '__excepthook__' , '__name__' , '__stderr__' , '__stdin__' , '__stdout__' , '_getframe' , 'api_version' , 'argv' , 'builtin_module_names' , 'byteorder' , 'callstats' , 'copyright' , 45 Учебник Python 3.1: Материал из Викиучебника. 'displayhook' , 'exc_info' , 'excepthook' , 'exec_prefix' , 'executable' , 'exit' , 'getdefaultencoding' , 'getdlopenflags' , 'getrecursionlimit' , 'getrefcount' , 'hexversion' , 'maxint' , 'maxunicode' , 'meta_path' , 'modules' , 'path' , 'path_hooks' , 'path_importer_cache' , 'platform' , 'prefix' , 'ps1' , 'ps2' , 'setcheckinterval' , 'setdlopenflags' , 'setprofile' , 'setrecursionlimit' , 'settrace' , 'stderr' , 'stdin' , 'stdout' , 'version' , 'version_info' , 'warnoptions' ] Будучи использованной без аргументов, функция dir() возвращает список имён, определённых в данный момент. >>> a = [ 1 , 2 , 3 , 4 , 5 ] >>> import fibo >>> fib = fibo.fib >>> dir () [ '__builtins__' , '__doc__' , '__file__' , '__name__' , 'a' , 'fib' , 'fibo' , 'sys' ] Обратите внимание, что список состоит из имён всех типов: переменных, модулей, функций и т.д. В возвращаемом функцией dir() списке не содержится встроенных функций и переменных. Если вы хотите получить их список, то они определены в стандартном модуле builtins : >>> import builtins >>> dir (builtins) [ 'ArithmeticError' , 'AssertionError' , 'AttributeError' , 'BaseException' , 'Buffer Error' , 'DeprecationWarning' , 'EOFError' , 'Ellipsis' , 'EnvironmentError' , 'Excep tion' , 'False' , 'FloatingPointError' , 'FutureWarning' , 'GeneratorExit' , 'IOError ' , 'ImportError' , 'ImportWarning' , 'IndentationError' , 'IndexError' , 'KeyError' , 'KeyboardInterrupt' , 'LookupError' , 'MemoryError' , 'NameError' , 'None' , 'NotImp lemented' , 'NotImplementedError' , 'OSError' , 'OverflowError' , 'PendingDeprecatio nWarning' , 'ReferenceError' , 'RuntimeError' , 'RuntimeWarning' , 'StopIteration' , 'SyntaxError' , 'SyntaxWarning' , 'SystemError' , 'SystemExit' , 'TabError' , 'True' , 'TypeError' , 'UnboundLocalError' , 'UnicodeDecodeError' , 'UnicodeEncodeError' , ' UnicodeError' , 'UnicodeTranslateError' , 'UnicodeWarning' , 'UserWarning' , 'ValueE rror' , 'Warning' , 'ZeroDivisionError' , '__build_class__' , '__debug__' , '__doc__' , '__import__' , '__name__' , 'abs' , 'all' , 'any' , 'basestring' , 'bin' , 'bool' , 'b uffer' , 'bytes' , 'chr' , 'chr8' , 'classmethod' , 'cmp' , 'compile' , 'complex' , 'cop yright' , 'credits' , 'delattr' , 'dict' , 'dir' , 'divmod' , 'enumerate' , 'eval' , 'ex ec' , 'exit' , 'filter' , 'float' , 'frozenset' , 'getattr' , 'globals' , 'hasattr' , 'h ash' , 'help' , 'hex' , 'id' , 'input' , 'int' , 'isinstance' , 'issubclass' , 'iter' , ' len' , 'license' , 'list' , 'locals' , 'map' , 'max' , 'memoryview' , 'min' , 'next' , 'o bject' , 'oct' , 'open' , 'ord' , 'pow' , 'print' , 'property' , 'quit' , 'range' , 'repr ' , 'reversed' , 'round' , 'set' , 'setattr' , 'slice' , 'sorted' , 'staticmethod' , 'st r' , 'str8' , 'sum' , 'super' , 'trunc' , 'tuple' , 'type' , 'vars' , 'zip' ] Пакеты Пакеты — способ структурирования пространств имён (namespaces) модулей Python за счёт использования имён модулей, разделённых точками („dotted module names“). Например, имя модуля A.B означает — подмодуль [39] с именем B в пакете с именем A . Также как использование модулей позволяет авторам различных модулей не заботиться о пересекающихся именах среди глобальных переменных, использование именования через точку позволяет авторам многомодульных пакетов (таких как NumPy или Python Imaging Library) не заботиться о конфликтах имён модулей. Допустим, вы собираетесь разработать набор модулей (пакет, package) для унифицированной работы со звуковыми файлами и звуковыми данными. Существует 46 Учебник Python 3.1: Материал из Викиучебника. множество форматов звуковых файлов (обычно их можно распознать по расширению, например: .wav, .aiff, .au). Таким образом, вам может понадобиться создать и поддерживать разрастающуюся коллекцию модулей для конвертирования между различными форматами файлов. Также вам наверняка захочется иметь побольше операций для обработки звуковых данных (таких как смешивание, добавление эха, применение функции эквалайзера, создание искусственного стерео-эффекта), поэтому в дополнение к этому вы будете писать нескончаемый поток модулей для исполнения этих операций. Вот возможная структура вашего пакета (выраженная в терминологии иерархической файловой системы): sound/ Пакет верхнего уровня __init__.py Инициализация пакета работы со звуком (sound) formats/ Подпакет для конвертирования форматов файлов __init__.py wavread.py (чтение wav) wavwrite.py (запись wav) aiffread.py (чтение aiff) aiffwrite.py (запись aiff) auread.py (чтение au) auwrite.py (запись au) effects/ Подпакет для звуковых эффектов __init__.py echo.py ( эхо ) surround.py ( окружение ) reverse.py ( обращение ) filters/ Подпакет для фильтров __init__.py equalizer.py ( эквалайзер ) vocoder.py ( вокодер ) karaoke.py ( караоке ) При импорте пакета Python ищет подкаталог пакета в каталогах, перечисленных в sys.path Файлы __init__.py необходимы для того, чтобы Python трактовал эти каталоги как содержащие пакеты. Это сделано во избежание нечаянного сокрытия правомерных модулей, встречающихся в дальнейшем по пути поиска, каталогами с часто используемыми именами, таким как " string ". В наипростейшем случае файл __init__.py может быть пустым, но в более сложных может содержать код инициализации пакета или устанавливать значение описанной ниже переменной __all__ Пользователи пакета могут импортировать из него конкретные модули, например: import sound.effects.echo Таким образом подгружается подмодуль sound.effects.echo . Ссылаться на него нужно используя его полное имя: sound.effects.echo.echofilter( input , output , delay = 0.7 , atten = 4 ) Другой способ импортирования подмодуля: from sound.effects import echo 47 Учебник Python 3.1: Материал из Викиучебника. Так тоже подгружается подмодуль echo , но теперь он доступен без префикса пакета, поэтому может использоваться следующим образом: echo.echofilter( input , output , delay = 0.7 , atten = 4 ) И еще один вариант — прямое импортирование желаемой функции или переменной: from sound.effects.echo import echofilter Опять же, таким образом подгружается подмодуль echo , но теперь его функция echofilter() может быть вызвана непосредственно: echofilter( input , output , delay = 0.7 , atten = 4 ) Заметьте, что при использовании выражения from пакет import элемент , элементом может быть подмодуль (или подпакет) пакета или любое другое имя, определённое в пакете - например, функция, класс или переменная. Оператор import сначала проверяет, определён ли элемент в пакете; если нет — он трактует его как модуль и пытается загрузить. Если не удается его найти, порождается исключение ImportError Напротив, при использовании синтаксиса в стиле import элемент.подэлемент.подэлемент , все элементы кроме последнего должны быть пакетами; последний элемент может быть модулем или пакетом, но не может быть классом, функцией или переменной, определёнными в предыдущем элементе. Импорт * из пакета Что происходит, когда пользователь пишет from sound.effects import * ? В идеале, мы бы надеялись, что таким образом код выходит в файловую систему и находит какие подмодули существуют в пакете, импортируя их все. К сожалению, такой метод не очень хорошо работает на платформах Windows, поскольку у файловой системы не всегда есть корректная информация о регистре имён файлов. На этих платформах нет гарантированного способа узнать, нужно ли импортировать файл ECHO.PY в качестве модуля echo , Echo или ECHO . (Например, у Windows 95 есть назойливая привычка показывать имена всех файлов с заглавной буквы.) Ограничение DOS на имя файла в формате 8+3 добавляет забавную проблему, связанную с длинными именами модулей. Единственный выход для автора пакета — предоставить его подробное содержание. Оператор import использует следующее соглашение: если в коде файла __init__.pyтекущего пакета определён список __all__ , то он полагается списком имён модулей, которые нужно импортировать в случае from пакет import * . На совести автора поддержка этого списка в соответствующем состоянии в каждой новой версии пакета. Впрочем, авторы пакета могут его не поддерживать вообще, если не видят смысла в импортировании * из их пакета. Например, файл sounds/effects/__init__.py может содержать следующий код: __all__ = [ "echo" , "surround" , "reverse" ] Это будет значить, что выражение from sound.effects import * импортирует три именованных подмодуля из пакета sound Если список __all__ не определён, оператор from Sound.Effects import * не импортирует все подмодули пакета sound.effects в текущее пространство имён: он лишь убеждается, что импортирован пакет sound.effects (возможно, выполняя код инициализации из __init__.py), а затем импортирует все определённые в пакете имена. В этот список попадают любые имена, определённые (и загруженные явно подмодулями) 48 |