Опубликован: 22.12.2005 | Доступ: свободный | Студентов: 17067 / 526 | Оценка: 4.18 / 3.71 | Длительность: 16:16:00
ISBN: 978-5-9556-0109-0
Лекция 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 >
Зураб Муциев
Зураб Муциев

Здравствуйте друзья, коллеги.

С кем из тьюторов вы работаете? Просто возникают вопросы, и хочется чтоб обяснили на примере как это происходит, гугл не всегда дает ответа.

Постить в соц сетях, там не всегда адекват, и чаще они базарят не по делу.

Андрей Егоров
Андрей Егоров

def bin(n):

"""Цифры двоичного представления натурального числа """

if n == 0:

   return []

n, d = divmod(n, 2)

return bin(n) + [d]

print bin(69)

Что значит здесь return[] ? Возвращает список? Непонятно какой список? Откуда он? 

 

 

Ольга Горбунова
Ольга Горбунова
Россия, липецк, мбоу сш №68, 2017
Александр Балабанов
Александр Балабанов
Россия, Москва, МТУ (МГУПИ)