Опубликован: 22.12.2005 | Уровень: для всех | Доступ: платный
Лекция 13:

Интеграция Python с другими языками программирования

< Лекция 12 || Лекция 13: 12345 || Лекция 14 >

Интеграция Python и других систем программирования

Язык программирования Python является сценарным языком, а значит его основное назначение - интеграция в единую систему разнородных программных компонентов. Выше рассматривалась (низкоуровневая) интеграция с C/C++-приложениями. Нужно заметить, что в большинстве случаев достаточно интеграции с использованием протокола. Например, интегрируемые приложения могут общаться через XML-RPC, SOAP, CORBA, COM, .NET и т.п. В случаях, когда приложения имеют интерфейс командной строки, их можно вызывать из Python и управлять стандартным вводом-выводом, переменными окружения. Однако есть и более интересные варианты интеграции.

Современное состояние дел по излагаемому вопросу можно узнать по адресу: http://www.python.org/moin/IntegratingPythonWithOtherLanguages

Java

Документация по Jython (это реализация Python на Java-платформе) отмечает, что Jython обладает следующими неоспоримыми преимуществами над другими языками, использующими Java-байт-код:

  • Jython-код динамически компилирует байт-коды Java, хотя возможна и статическая компиляция, что позволяет писать апплеты, сервлеты и т.п.;
  • Поддерживает объектно-ориентированную модель Java, в том числе, возможность наследовать от абстрактных Java-классов;
  • Jython является реализацией Python - языка с практичным синтаксисом, обладающего большой выразительностью, что позволяет сократить сроки разработки приложений в разы.

Правда, имеются и некоторые ограничения по сравнению с "обычным" Python. Например, Java не поддерживает множественного наследования, поэтому в некоторых версиях Jython нельзя наследовать классы от нескольких Java-классов (в то же время, множественное наследование поддерживается для Python-классов).

Следующий пример (файл lines.py) показывает полную интеграцию Java-классов с интерпретатором Python:

# Импортируются модули из Java
                from java.lang import System
                from java.awt import *
                # А это модуль из Jython
                import random

                # Класс для рисования линий на рисунке
                class Lines(Canvas):
                  # Реализация метода paint()
                  def paint(self, g):
                    X, Y = self.getSize().width, self.getSize().height
                    label.setText("%s x %s" % (X, Y))
                    for i in range(100):
                      x1, y1 = random.randint(1, X), random.randint(1, Y)
                      x2, y2 = random.randint(1, X), random.randint(1, Y)
                      g.drawLine(x1, y1, x2, y2)

                # Метки, кнопки и т.п.
                panel = Panel(layout=BorderLayout())
                label = Label("Size", Label.RIGHT)
                panel.add(label, "North")
                button = Button("QUIT", actionPerformed=lambda e: System.exit(0))
                panel.add(button, "South")
                lines = Lines()
                panel.add(lines, 'Center')

                # Запуск панели в окне
                import pawt
                pawt.test(panel, size=(240, 240))

Программы на Jython можно компилировать в Java и собирать в jar-архивы. Для создания jar-архива на основе модуля (или пакета) можно применить команду jythonc, которая входит в комплект Jython. Из командной строки это можно сделать примерно так:

jythonс -d -c -j lns.jar lines.py

Для запуска приложения достаточно запустить lines из командной строки:

java -classpath "$CLASSPATH" lines

В переменной $CLASSPATH должны быть пути к архивам lns.jar и jython.jar.

Prolog

Для тех, кто хочет использовать Prolog из Python, существует несколько возможностей:

Эти три варианта реализуют различные способы интеграции возможностей Prolog в Python. Первый вариант использует SWIG, второй организует общение с Prolog-системой через конвейер, а третий является специализированной реализацией Prolog.

Следующий пример показывает использование модуля pylog:

from pylog import *

                exec(compile(r"""
                man('Socrates').
                man('Democritus').
                mortal(X) :- man(X).
                """))

                WHO = Var()
                queries = [mortal('Socrates'),
                           man(WHO),
                           mortal(WHO)]
                for query in queries:
                  print "?", query
                  for _ in query():
                    print "    yes:", query

Что выдает результат:

? mortal(Socrates)
                    yes: mortal(Socrates)
                ? man(_)
                    yes: man(Socrates)
                    yes: man(Democritus)
                ? mortal(_)
                    yes: mortal(Socrates)
                    yes: mortal(Democritus)

Разумеется, это не "настоящий" Prolog, но с помощью модуля pylog любой, кому требуются логические возможности Prolog в Python, может написать программу с использованием Prolog-синтаксиса.

OCaml

Язык программирования OCaml - это язык функционального программирования (семейства ML, что означает Meta Language), созданный в институте INRIA, Франция. Важной особенностью OCaml является то, что его компилятор порождает исполняемый код, по быстродействию сравнимый с С, родной для платформ, на которых OCaml реализован. В то же время, будучи функциональным по своей природе, он приближается к Python по степени выразительности. Именно поэтому для OCaml была создана библиотека Pycaml, фактически реализующая аналог C API для OCaml. Таким образом, в программах на OCaml могут использоваться модули языка Python, в них даже может быть встроен интерпретатор Python. Для Python имеется большое множество адаптированных C-библиотек, это дает возможность пользователям OCaml применять в разработке комбинированное преимущество Python и OCaml. Минусом является только необходимость знать функции Python/C API, имена которого использованы для связи OCaml и Python.

Следующий пример (из Pycaml) показывает программу для OCaml, которая определяет модуль для Python на OCaml и вызывает встроенный интерпретатор Python:

let foo_bar_print = pywrap_closure
                  (fun x -> pytuple_fromarray (pytuple_toarray x)) ;;
                let sd = pyimport_getmoduledict () ;;
                let mx = pymodule_new "CamlModule" ;;
                let cd = pydict_new () ;;
                let cx = pyclass_new (pynull (), cd, pystring_fromstring "CamlClass") ;;
                let cmx = pymethod_new (foo_bar_print,(pynull ()),cx) ;;
                let _ = pydict_setitemstring (cd, "CamlMethod", cmx) ;;
                let _ = pydict_setitemstring (pymodule_getdict mx, "CamlClass", cx) ;;
                let _ = pydict_setitemstring (sd, "CamlModule", mx) ;;
                let _ = pyrun_simplestring
                  ("from CamlModule import CamlClass\n" ^
                   "x = CamlClass()\n" ^
                   "for i in range(100000):\n" ^
                   "  x.CamlMethod(1,2,3,4)\n" ^
                   "print 'Done'\n")

Pyrex

Для написания модулей расширения можно использовать специальный язык - Pyrex - который совмещает синтаксис Python и типы данных C. Компилятор Pyrex написан на Python и превращает исходный файл (например, primes.pyx) в файл на C - готовый для компиляции модуль расширения. Язык Pyrex заботится об управлении памятью, удаляя после себя ставшие ненужными объекты. Пример файла из документации к Pyrex (для вычисления простых чисел):

def primes(int kmax):
                  cdef int n, k, i
                  cdef int p[1000]
                  result = []
                  if kmax > 1000:
                    kmax = 1000
                  k = 0
                  n = 2
                  while k < kmax:
                    i = 0
                    while i < k and n % p[i] <> 0:
                      i = i + 1
                    if i == k:
                      p[k] = n
                      k = k + 1
                      result.append(n)
                    n = n + 1
                  return result

В результате применения компилятора Pyrex, нехитрой компиляции и компоновки (с помощью GCC):

pyrexc primes.pyx
                gcc primes.c -c -fPIC -I /usr/local/include/python2.3
                gcc -shared primes.o -o primes.so

Получается модуль расширения с функцией primes():

>>> import primes
                >>> primes.primes(25)
                [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
                67, 71, 73, 79, 83, 89, 97]

Разумеется, в Pyrex можно использовать C-библиотеки, именно поэтому он, как и SWIG, может служить для построения оберток C-библиотек для Python.

Следует отметить, что для простых операций Pyrex применяет C, а для обращения к объектам Python - вызовы Python/C API. Таким образом, объединяется выразительность Python и эффективность C. Конечно, некоторые вещи в Pyrex не доступны, например, генераторы, списковые включения и Unicode, однако, цель Pyrex - создание быстродействующих модулей расширения, и для этого он превосходно подходит. Ознакомится с Pyrex можно по документации (которая, к сожалению, есть пока только на английском языке).

Заключение

В этой лекции кратко рассматривались основные возможности интеграции интерпретатора Python и других систем программирования. Базовая реализация языка Python написана на C, поэтому Python имеет программный интерфейс Python/C API, который позволяет программам на C/C++ обращаться к интерпретатору Python, отдельным объектам, модулям и типам данных. Состав Python/C API достаточно обширен, поэтому речь шла лишь о некоторых основных его элементах.

Был рассмотрен процесс написания модуля расширения на C как напрямую, так и с использованием генератора интерфейсов SWIG. Также кратко говорилось о возможности встраивания интерпретатора Python в программу на С или OCaml.

Язык Python (с помощью специальной его реализации - Jython) прозрачно интегрируется с языком Java: в Python-программе, выполняемой под Jython в Java-апплете или Java-приложении, можно использовать практически любые Java-классы.

На примере языка Prolog были показаны различные подходы к добавлению возможностей логического вывода в Python-программы: независимая реализация Prolog-машины, связь с Prolog-интерпретатором через конвейер, связь через Python/C API.

Интересный гибрид C и Python представляет из себя язык Pyrex. Этот язык создан с целью упростить написание модулей расширения для Python на C, и использует структуры данных C и подобный Python синтаксис. Несмотря на некоторые смысловые и синтаксические отличия как от C, так и от Python, язык Pyrex помогает существенно сократить время разработки модулей расширения, сохранив эффективность компилятора C и знакомый синтаксис Python.

В данной лекции не были представлены другие возможности интеграции, например библиотека шаблонов C++ Boost Python, которая позволяет интегрировать Python и C++. Кроме того, из Python можно использовать библиотеки, написанные на Фортране (проект F2PY).

Развитые и гибкие интеграционные возможности Python являются его основным преимуществом в качестве языка для интеграции приложений. Из лекции нетрудно заключить, что Python легко взаимодействует с другими системами.

Ссылки

Библиотека Boost Python для C++ http://www.boost.org

< Лекция 12 || Лекция 13: 12345 || Лекция 14 >
Сергей Крупко
Сергей Крупко

Добрый день.

Я сейчас прохожу курс  повышения квалификации  - "Профессиональное веб-программирование". Мне нужно получить диплом по этому курсу. Я так полагаю нужно его оплатить чтобы получить диплом о повышении квалификации. Как мне оплатить этот курс?

 

Павел Ялганов
Павел Ялганов

Скажите экзамен тоже будет ввиде теста? или там будет какое то практическое интересное задание?

Максим Чиндясов
Максим Чиндясов
Россия, Нижний Новгород
Ольга Коваль
Ольга Коваль
Беларусь, Минск