справочник по Python. мм isbn 9785932861578 9 785932 861578
Скачать 4.21 Mb.
|
768 Глава 26. Расширение и встраивание интерпретатора Python Дополнительные возможности расширения и встраивания Создание модулей расширений вручную или использование модуля ctypes обычно не вызывает сложностей, если программный код расширения на языке C достаточно прост. Однако с ростом сложности расширения процесс его создания быстро может стать весьма трудоемким. Поэтому у вас может появиться желание отыскать подходящий инструмент создания расшире- ний. Подобные инструменты либо автоматизируют большую часть процес- са создания расширения, либо предоставляют программный интерфейс, позволяющий работать на более высоком уровне. Ссылки на различные инструменты можно найти на странице http://wiki.python.org/moin/Integr atingPythonWithOtherLanguages . Ниже приводится короткий пример ис- пользования инструмента SWIG (http://www.swig.org), исключительно в де- монстрационных целях. Для полноты информации следует отметить, что первоначально инструмент SWIG был создан автором книги. Используя инструменты автоматизации, программист обычно лишь созда- ет описание содержимого модуля расширения на верхнем уровне. Напри- мер, при использовании SWIG создается лишь краткая спецификация ин- терфейса, которая выглядит, как показано ниже: /* example.i : Пример спецификации Swig */ %module example %{ /* Преамбула. Здесь выполняется подключение всех заголовочных файлов */ #include “example.h” %} /* Содержимое модуля. Здесь перечисляются все объявления на языке C */ typedef struct Point { double x; double y; } Point; extern int gcd(int, int); extern int replace(char *s, char oldch, char newch); extern double distance(Point *a, Point *b); Используя такую спецификацию, SWIG автоматически генерирует все, что должно содержаться в модуле расширения на языке Python. Чтобы запу- Python. Чтобы запу- . Чтобы запу- стить SWIG, достаточно просто вызвать его как компилятор: % swig –python example.i % В результате создается набор файлов с расширениями .c и .py. При этом вам очень редко придется беспокоиться об их содержимом. Если вы поль- зуетесь пакетом distutils, включите файл спецификации с расширением .i в параметры настройки в файле setup.py; это обеспечит автоматический запуск SWIG при сборке расширения. Например, ниже приводится при- SWIG при сборке расширения. Например, ниже приводится при- при сборке расширения. Например, ниже приводится при- мер содержимого файла setup.py, который, благодаря включению файла example.i , автоматически запускает SWIG. # setup.py from distutils.core import setup, Extension Jython и IronPython 769 setup(name=”example”, version=”1.0”, py_modules = [‘example.py’], ext_modules = [ Extension(“_example”, [“example.i”,”example.c”]) ] ) Оказывается, что такого файла example.i и файла setup.py вполне достаточ- но, чтобы создать действующий модуль расширения. Если выполнить ко- манду python setup.py build_ext --inplace, она создаст полностью работоспо- собное расширение в каталоге. Jython и IronPython Возможности расширения и встраивания не ограничиваются программа- ми на языке C. Тем, кто работает с языком Java, можно порекомендовать обратить внимание на Jython (http://www.jython.org) – полноценную реали- зацию интерпретатора Python на языке Java. Интерпретатор jython позво- ляет легко и просто импортировать библиотеки Java с помощью привыч- Java с помощью привыч- с помощью привыч- ной инструкции import. Например: bash-3.2$ jython Jython 2.2.1 on java1.5.0_16 Type “copyright”, “credits” or “license” for more information. >>> from java.lang import System >>> System.out.println(“Hello World”) Hello World >>> Тем, кто работает с фреймворком .NET в Windows, можно порекомендо- NET в Windows, можно порекомендо- в Windows, можно порекомендо- Windows, можно порекомендо- , можно порекомендо- вать обратить внимание на IronPython (http://www.codeplex.com/Wiki/View. aspx?ProjectName=IronPython ) – полноценную реализацию интерпретато- ра Python на языке C#. Интерпретатор IronPython обеспечивает простой доступ к любым библиотекам .NET из программного кода на языке Python. Например: % ipy IronPython 1.1.2 (1.1.2) on .NET 2.0.50727.42 Copyright (c) Microsoft Corporation. All rights reserved. >>> import System.Math >>> dir(System.Math) [‘Abs’, ‘Acos’, ‘Asin’, ‘Atan’, ‘Atan2’, ‘BigMul’, ‘Ceiling’, ‘Cos’, ‘Cosh’, ... ] >>> System.Math.Cos(3) -0.9899924966 >>> Подробное рассмотрение интерпретаторов Jython и IronPython выходит далеко за рамки этой книги. Тем не менее имейте в виду, что оба они явля- ются интерпретаторами языка Python, главное различие между которыми заключается в их библиотеках. Приложение A . Python 3 В декабре 2008 года вышла версия Python 3.0. Изменения в языке Python оказались настолько существенными, что была нарушена обратная совме- стимость с Python 2 во многих важных областях. Достаточно полный обзор изменений в версии Python 3 можно найти в документе «What’s New in Py- Python 3 можно найти в документе «What’s New in Py- 3 можно найти в документе «What’s New in Py- What’s New in Py- ’s New in Py- s New in Py- New in Py- New in Py- in Py- in Py- Py- Py- thon 3.0» (Что нового в Python 3.0), доступном по адресу http://docs.python. org/3.0/whatsnew/3.0.html 1 . В некотором смысле, первые 26 глав этой книги можно рассматривать, как диаметральную противоположность документу «What’s New». Основное внимание в этих главах уделялось особенностям, которые являются общими для Python 2 и Python 3, включая модули стан- дартной библиотеки, основные возможности языка и примеры. Кроме не- скольких незначительных различий в именах и того факта, что инструк- ция print() стала функцией, никаких уникальных особенностей Python 3 в этой книге не рассматривалось. Основная цель этого приложения состоит в том, чтобы дать описание новых возможностей языка Python, доступных только в версии 3, а также позна- Python, доступных только в версии 3, а также позна- , доступных только в версии 3, а также позна- комить с некоторыми важными отличиями тех, кто планирует перевести существующий программный код на использование новой версии. В конце этого приложения приводятся несколько стратегий перехода и описывает- ся утилита 2to3, позволяющая упростить такой переход. Кто должен использовать Python 3? Прежде чем двинуться дальше, важно ответить на вопрос: «Кто должен ис- пользовать версию Python 3.0?». В сообществе пользователей Python всегда было известно, что переход на использование Python 3 будет происходить постепенно и что ветка Python 2 будет поддерживаться еще в течение не- Python 2 будет поддерживаться еще в течение не- 2 будет поддерживаться еще в течение не- которого времени (речь идет о годах). К моменту написания этих строк не было никакой срочной необходимости отказываться от программного кода, написанного для версии Python 2. Я полагаю, что даже спустя не- Python 2. Я полагаю, что даже спустя не- 2. Я полагаю, что даже спустя не- 1 Аналогичную информацию (хотя это и не прямой перевод указанного документа) на русском языке можно найти на странице http://www.ibm.com/developerworks/ ru/library/l-python3-1/. – Прим. перев. Новые возможности языка 771 сколько лет, когда увидит свет пятое издание этой книги, в разработке все еще будет находиться огромный объем программного кода для Python 2. Главная проблема, которая возникает при переходе на Python 3.0, связана с совместимостью со сторонними библиотеками. Мощь языка Python в зна- Python в зна- в зна- чительной степени обусловлена огромным разнообразием фреймворков и библиотек. Однако без явного вмешательства в реализацию этих библио- тек они в подавляющем большинстве не способны работать под управлени- ем Python 3. Эта проблема осложняется еще и тем, что многие библиотеки зависят от других библиотек, которые в свою очередь зависят от еще боль- шего количества библиотек. К моменту написания этих строк (2009 год) еще существовали библиотеки и фреймворки для языка Python, которые не были даже перенесены на версию Python 2.4, не говоря уже о версии 2.6 или 3.0. Поэтому, если вы предполагаете использовать сторонний про- граммный код, лучше пока остановиться на версии Python 2. Если вы чи- Python 2. Если вы чи- 2. Если вы чи- таете эту книгу в 2012 году, можно надеяться, что ситуация значительно улучшилась. Несмотря на то что в версии Python 3 были ликвидированы многие недо- Python 3 были ликвидированы многие недо- 3 были ликвидированы многие недо- статки языка, тем не менее пока еще трудно сказать, что Python 3 является достаточно обоснованным выбором для начинающих пользователей, кото- рые только пытаются освоить основы языка. Практически вся докумен- тация, руководства, сборники рецептов и примеров написаны в предполо- жении использования Python 2 и используют стиль программирования, несовместимый с Python 3. Разумеется, трудно получить положительный результат при обучении, если практически все примеры оказываются не- работоспособными. Даже официальная документация до сих пор не пол- ностью учитывает особенности программирования для версии Python 3; в процессе работы над книгой автор отправил огромное количество отчетов об ошибках, касающихся неточностей и упущений в документации. Наконец, хотя Python 3.0 подается, как самая последняя и самая лучшая версия, тем не менее в ней немало проблем, связанных с производительно- стью и особенностями поведения. Например, система ввода-вывода в пер- вых выпусках страдала недопустимо низкой производительностью. Раз- деление строк на строки байтов и строки Юникода также принесло свои проблемы. Даже некоторые встроенные модули оказались неработоспособ- ными из-за изменений в системе ввода-вывода и в реализации механизма работы со строками. Очевидно, что с течением времени эти проблемы бу- дут сняты, – по мере того, как все больше программистов будут участво- вать в тестировании новых версий. Однако, по мнению автора этой книги, версия Python 3.0 пока пригодна лишь для экспериментального исполь- Python 3.0 пока пригодна лишь для экспериментального исполь- 3.0 пока пригодна лишь для экспериментального исполь- зования опытными ветеранами Python. Если вам требуется стабильность и высокая надежность, продолжайте пользоваться Python 2, пока в ветке Python 3 не будут устранены основные неувязки. Новые возможности языка В этом разделе рассматриваются некоторые новые возможности Python 3, которые не поддерживаются в Python 2. 772 Приложение A. Python 3 Кодировка исходных текстов и идентификаторы В Python 3 предполагается, что исходные тексты программ набирают- Python 3 предполагается, что исходные тексты программ набирают- 3 предполагается, что исходные тексты программ набирают- ся в кодировке UTF-8. Кроме того, были ослаблены требования к набору символов, которые могут использоваться в идентификаторах. В частности, идентификаторы могут включать любые допустимые символы Юникода с кодовыми пунктами от U+0080 и выше. Например: π = 3.141592654 r = 4.0 print(2* π*r) Однако наличие возможности использовать такие символы в исходных текстах еще не означает, что ею следует бездумно пользоваться. Не все текстовые редакторы, терминалы и инструменты разработчика одинаково хорошо обрабатывают символы Юникода. Кроме того, для программистов может оказаться чрезвычайно неудобным нажимать неуклюжие комбина- ции клавиш, чтобы ввести символы, отсутствующие на стандартной кла- виатуре (не говоря уже о том, что это может подтолкнуть седобородых ха- керов рассказать вам одну забавную историю о языке APL). Поэтому луч- APL). Поэтому луч- ). Поэтому луч- ше всего оставить символы Юникода исключительно для использования в комментариях и в литералах строк. Литералы множеств Множество элементов теперь можно определить, как литерал, заключив коллекцию значений в фигурные скобки { элементы }. Например: days = { ‘Mon’, ‘Tue’, ‘Wed’, ‘Thu’, ‘Fri’, ‘Sat’, ‘Sun’ } Этот синтаксис повторяет синтаксис использования функции set(): days = set([‘Mon’, ‘Tue’, ‘Wed’, ‘Thu’, ‘Fri’, ‘Sat’, ‘Sun’]) Генераторы множеств и словарей Конструкция вида { expr for x in s if condition } – это генератор множе- ства. Она применяет выражение expr ко всем элементам множества s и мо- жет использоваться на манер генераторов списков. Например: >>> values = { 1, 2, 3, 4 } >>> squares = {x*x for x in values} >>> squares {16, 1, 4, 9} >>> Конструкция вида { kexpr:vexpr for k,v in s if condition } – это генератор словаря. Она выполняет указанную операцию над всеми ключами и значе- . Она выполняет указанную операцию над всеми ключами и значе- Она выполняет указанную операцию над всеми ключами и значе- ниями в последовательности s кортежей (key, value) и возвращает словарь. Ключами нового словаря будут результаты выражения kexpr, а значения- ми – результаты выражения vexpr. Данную конструкцию можно рассма- тривать, как улучшенную версию функции dict(). Чтобы проиллюстрировать использование этой конструкции, предполо- жим, что у нас имеется файл ‘prices.dat’ с котировками акций: Новые возможности языка 773 GOOG 509.71 YHOO 28.34 IBM 106.11 MSFT 30.47 AAPL 122.13 Н иже приводится программа, которая читает содержимое файла в сло- варь, отображающий имена компаний в стоимость акций, используя гене- ратор словаря: fields = (line.split() for line in open(“prices.dat”)) prices = {sym:float(val) for sym,val in fields} В следующем примере реализовано приведение всех символов ключей это- го словаря к нижнему регистру: d = {sym.lower():price for sym,price in prices.items()} В следующем примере создается словарь, который содержит названия ком- паний, цена акций которых превышает $100.00: d = {sym:price for sym,price in prices.items() if price >= 100.0} Расширенная операция распаковывания итерируемых объектов В Python 2 элементы в итерируемых объектах могут распаковываться в от- Python 2 элементы в итерируемых объектах могут распаковываться в от- 2 элементы в итерируемых объектах могут распаковываться в от- дельные переменные, как показано ниже: items = [1,2,3,4] a,b,c,d = items # Распакует элементы в переменные Чтобы выполнить распаковывание, количество переменных должно точно соответствовать количеству распаковываемых элементов. В Python 3, чтобы распаковать лишь некоторые элементы последователь- Python 3, чтобы распаковать лишь некоторые элементы последователь- 3, чтобы распаковать лишь некоторые элементы последователь- ности, можно использовать имя переменной с шаблонным символом, куда будут сохраняться оставшиеся значения в виде списка. Например: a,*rest = items # a = 1, rest = [2,3,4] a,*rest,d = items # a = 1, rest = [2,3], d = 4 *rest, d = items # rest = [1,2,3], d = 4 В этих примерах переменная, имени которой предшествует символ *, при- нимает все оставшиеся значения и сохраняет их в виде списка. Если лиш- ние элементы отсутствуют в объекте, список может остаться пустым. Один из примеров использования такой возможности – циклический обход спи- сков кортежей (или последовательностей), когда кортежи могут иметь раз- личные размеры. Например: points = [ (1,2), (3,4,”red”), (4,5,”blue”), (6,7) ] for x,y, *opt in points: if opt: # Обработка дополнительных полей инструкции 774 Приложение A. Python 3 В этой конструкции может употребляться не более одной переменной со звездочкой. Нелокальные переменные Вложенные функции могут изменять значения переменных в объемлю- щих функциях, используя объявление nonlocal. Например: def countdown(n): def decrement(): nonlocal n n -= 1 while n > 0: print(“T-minus”, n) decrement() В Python 2 вложенные функции могут только прочитать значение перемен- Python 2 вложенные функции могут только прочитать значение перемен- 2 вложенные функции могут только прочитать значение перемен- ной, объявленной в объемлющей функции, но не могут изменить его. Объ- явление nonlocal обеспечивает такую возможность. Аннотации функций Аргументы и возвращаемое значение функции могут быть аннотированы произвольными значениями. Например: def foo(x:1,y:2) -> 3: pass Функции имеют атрибут __annotations__, который является словарем, ото- бражающим имена аргументов в аннотированные значения. Специальный ключ ‘return’ отображается в аннотированное возвращаемое значение. На- пример: >>> foo.__annotations__ {‘y’: 4, ‘x’: 3, ‘return’: 5} >>> Интерпретатор никак не использует эти аннотации. В действительности, они могут иметь любые значения. Однако, как предполагается, эта инфор- мация может быть полезна в будущем. Например, можно было бы написать такой код: def foo(x:int, y:int) -> str: инструкции Аннотация не обязана быть представлена единственным значением. В ка- честве аннотации может использоваться любое выражение, допустимое в языке Python. Для переменных, обозначающих коллекции позиционных и именованных аргументов, используется тот же синтаксис. Например: def bar(x, *args:”additional”, **kwargs:”options”): инструкции Следует отметить еще раз, что интерпретатор Python никак не использу- Python никак не использу- никак не использу- ет аннотации. Как предполагается, они будут использоваться сторонними библиотеками и фреймворками для различных нужд, связанных с мета- Новые возможности языка 775 программированием. В качестве примеров можно назвать инструменты статического анализа, документирования, тестирования, механизмы пере- грузки функций, маршаллинга, вызова удаленных процедур, интегриро- ванные системы разработки, средства проверки соблюдения соглашений и так далее. Ниже приводится пример функции-декоратора, который про- веряет аргументы и возвращаемые значения функций: def ensure(func): # Извлечь аннотированные данные return_check = func.__annotations__.get(‘return’,None) arg_checks = [(name,func.__annotations__.get(name)) for name in func.__code__.co_varnames] ёёё # Создать обертку, которая будет проверять значения аргументов и # возвращаемый результат с помощью функций, указанных в аннотациях def assert_call(*args,**kwargs): for (name,check),value in zip(arg_checks,args): if check: assert check(value), “%s %s” % (name, check.__doc__) for name,check in arg_checks[len(args):]: if check: assert check(kwargs[name]), “%s %s” % (name, check.__doc__) result = func(*args,**kwargs) assert return_check(result), “return %s” % return_check.__doc__ return result ёёё return assert_call Ниже приводится пример использования этого декоратора: def positive(x): “must be positive” return x > 0 ёёё def negative(x): “must be negative” return x < 0 ёёё @ensure def foo(a:positive, b:negative) -> positive: return a – b Ниже приводятся несколько примеров вызова этой функции: >>> |