Консалтинг и автоматизация в области управления
эффективностью банковского бизнеса

Журнал ВРМ World

XML-RPC на языке Python

В недалеком прошлом задачи взаимодействия систем автоматизации приводили специалистов в уныние своей сложностью. Повсеместная доступность интернета и простота протоколов открыли новую перспективу в этом вопросе, и теперь Вам нужно думать не о сложности задачи, а о том какой инструмент для этого выбрать.

Две наиболее популярных среды, Enterprise JavaBeans и Microsoft COM, являются очень выразительными и надежными, но одновременно и достаточно сложными. Они привносят в процесс очень много дополнительной работы. Другие характеристики, например, способность работать на разных платформах и с различными языками, только усложняют проблему выбора между ними. Не так давно нашему вниманию был представлен протокол SOAP (Simple Object Access Protocol), призванный решить многие из этих проблем. Протокол SOAP уже имеет несколько неполных реализаций и уже используется, однако он все еще находится на этапе изменений. Некоторые реализации пока не могут взаимодействовать друг с другом.

Так что же делать разработчику?

До этого момента разработчики просто использовали то, что сегодня имеется под рукой и способно работать. А работал как раз XML-RPC. Он прост, эффективен и последователен. XML-RPC вполне может выполнять роль "клея", к чему неспособен его "старший брат" - SOAP. Если вы ищите крупномасштабную среду для взаимосвязи разнородных серверов и функциональности, аналогичной автоматическому поиску услуг, то XML-RPC вам не подойдет. XML-RPC - это быстрое, простое в использовании и надежное средство взаимодействия распределенных систем, не зависящее от языков, используемых сторонами. XML-RPC представляет собой гибридное решение. Он не является объектно-ориентированным в строгом смысле этого слова. "RPC" в аббревиатуре означает "Remote Procedure Call" (удаленный вызов процедур). RPC очень прост - пользователь посылает запрос по сети и получает отклик. Если это звучит подозрительно знакомо - так оно и есть, ведь привычный нам Интернет работает именно по такой схеме. По RPC колокол прозвонил в еще 90х годах. Его разработчики оказались не способны стандартизировать структуру данных. Компания Sun действительно попыталась реализовать стандарт в XDR. Но в обиход он так никогда полностью и не вошел. С развитием объектно-ориентированного программирования, RPC впал в немилость. С дополнением RPC языком XML, процесс получил популярную стандартную структуру представления данных, что вдохнуло новую жизнь в RPC. Но все-таки - зачем его использовать?

Основная и бесспорная причина для использования XML-RPC состоит в том, что он работает, и работает достаточно хорошо. Разработчик затрачивает минимум усилий на установку и использование библиотеки xmlrpclib языка Python, взаимодействующую с серверами, построенными на основе Python, PHP, Java, Perl, C++ и даже COM. Целая глава, посвященная XML-RPC в бестселлере "Java and XML", уделяет большое внимание XML-RPC. В мире языка Python наиболее широко XML-RPC используется в Zope. Zope мог обращаться и отвечать на XML-RPC с середины 1999 года.

Библиотека xmlrpclib компании PythonWare

В отличие от других языков его поколения, Python всегда имел возможности для создания постоянных объектов. Спектр этих возможностей постоянно расширяется, от стандартных библиотечных пакетов ("marshall"), преобразующих простые объекты для хранения в плоских файлах, до базы данных "Zope Object Database," которая по своим возможностям соперничает с коммерческими объектно-ориентированными базами данных (OODB). Маршалинг представляет собой перевод объекта из внутреннего представления одной программы в некий независимый формат. В контексте библиотеки xmlrpclib, маршаллинг объекта языка Python означает конвертацию его в вызов XML-RPC. Обратный маршаллинг (unmarshalling) представляет собой обратный процесс.

Написанная Фредериком Ландом из PythonWare, библиотека xmlrpclib скрывает всю сложность в объектах прямого и обратного маршаллинга. Таким же образом скрываются подробности соединения с сервером, передачи запроса и получения ответа.

Вы можете загрузить последнюю версию xmlrpclib.py (и получить дополнительную информацию об этой библиотеке) на странице XML-RPC для языка Python.

XML-RPC и Meerkat

Рэйл Дорнфест, являющийся основной движущей силой в продвижении XML в среде PHP, создал достаточно естественный интерфейс XML-RPC к Meerkat, службе открытого доступа, объединяющей новостную информацию из множества источников с помощью RSS. Давайте воспользуемся этим уже готовым сервером для наших примеров. Первым делом мы импортируем модуль "красивой" печати (pprint) из Python Standard Library. Некоторые из выходных данных Meerkat достаточно длинны.


>>> from pprint import pprint

После импорта xmlrpclib, подсоединяемся к серверу с помощью xmlrpclib, состоящей из одной строки:


>>> meerkatsvr = xmlrpclib.server("http://www.oreillynet.com/meerkat/xml-rpc/server.php")

Здесь мы создаем пример сервера XML-RPC, способного соединяться, отсылать и получать XML-RPC. С помощью рекурсии этот сервер может даже понимать вложенные запросы XML-RPC.

Теперь давайте запросим список методов, имеющихся на сервере:


>>> pprint(meerkatsvr.system.listMethods())
['meerkat.getChannels',
'meerkat.getCategories',
'meerkat.getChannelsByCategory',
'meerkat.getItems',
'system.listMethods',
'system.methodHelp',
'system.methodSignature']


Вы только что использовали XML-RPC для соединения с сервером через Интернет и получили отклик. Помимо простоты такого подхода, отметьте, что форма результата, возвращенного xmlrpclib, представляет собой "родной" список языка Python.

Получение списка каналов от Meerkat

Meerkat группирует каналы в темы, называемые категориями. Например, каналы, относящиеся к XML, находятся в категории 23. Если вы хотите получить список каналов для специфической темы, вы можете отправить Meerkat следующий запрос:


>>> pprint(meerkatsvr.meerkat.getChannelsByCategory(23))
[{'title': '<XML>fr', 'id': 2991},
{'title': '4xt', 'id': 2559},
{'title': 'Eclectic', 'id': 555},
{'title': 'eXploringXML', 'id': 4471},
{'title': 'eXploringXML Channel', 'id': 1105},
{'title': 'finetuning com', 'id': 107},
{'title': 'finetuning.com', 'id': 4628},
{'title': 'Free XML tools', 'id': 906},
{'title': 'JabberCentral Recent Jabber News', 'id': 4655},
{'title': 'Moreover XML and metadata news', 'id': 2243},
{'title': 'moreover... XML and metadata news', 'id': 683},
{'title': 'My Userland', 'id': 1945},
{'title': "O'Reilly Network XML FAQs", 'id': 2365},
{'title': 'oreillynet.xml', 'id': 989},
{'title': 'oreillynet.xmldev', 'id': 990},
{'title': 'SOAP Webservices Resource Center', 'id': 2022},
{'title': 'XML About com', 'id': 2435},
{'title': 'XML News from PerlXML.com', 'id': 718},
{'title': 'XML XSL Portal', 'id': 4460},
{'title': 'XML.com', 'id': 47},
{'title': 'XML.com Resource Guide', 'id': 4637},
{'title': 'xmlhack', 'id': 724},
{'title': 'xmlTree Newsletter', 'id': 413}]

Заглянем еще глубже в XML-RPC и Meerkat

В своей статье по программированию web-клиента, я продемонстрировал, как можно легко загрузить список всех Linux-статей Meerkat с помощью мощной библиотеки URLLIB языка Python и очень простого скрипта. Давайте вернемся к этой задаче, используя xmlrpclib. Воспользовавшись даже более простым скриптом, мы можем устранить некоторые неоднозначные и неуклюжие моменты предыдущего подхода и создать более надежное приложение.

Откройте новую интерактивную сессию на языке Python, импортируйте xmlrpclib и создайте запрос сервера (server instance) для взаимодействия с сервером Meerkat:


>>> import xmlrpclib
>>> meerkatURI = http://www.oreillynet.com/meerkat/xml-rpc/server.php)
>>> meerkatsvr = xmlrpclib.Server(meerkatURI)


Прежде чем мы начнем составлять код для нашего обновленного решения, давайте изучим некоторые характеристики, встроенные Рэйлом Дорнфестом в сервер Meerkat XML-RPC для отражения его возможностей. Мы уже видели system.listMethods(). Он возвращает текущий список имеющихся на сервере методов. Вы можете получить подпись метода для любого из этих методов, вызвав methodSignature():


>>> meerkatsvr.system.methodSignature(methodname)

Эта строка возвращает двухэлементный массив, содержащий возвращаемую величину и параметр (параметры) указанного метода. Заметьте, что вам не следует включать закрывающие скобки после названия метода.

Дорнфест также предложил средства, позволяющие получать справку по любому методу сервера.


>>> meerkatsvr.system.methodHelp(meerkat.getItems)

Чтобы увидеть этот и другие методы, доступные для клиентов XML-RPC Meerkat, посетите тестовую страницу интерфейса Meerkat XML-RPC. Выбор пункта "Самодиагностика" (introspection) из выпадающего списка позволит вам увидеть все имеющиеся методы вместе с их документацией. Если имеется URI, он также тестирует сервер Meerkat XML-RPC Server, возвращая и вызов методов и ответ сервера. Отлично.

Получение от Meerkat списка статей Linux

Как вы, возможно, помните, задачей программы в моей статье по программированию web-клиента было получение ссылок на статьи Linux от Meerkat за прошедший час. После создания среды доступа к серверу с помощью URLLIB, мы сформировали URI:


http://www.oreillynet.com/meerkat/?p=5&t=1HOUR&_fl=minimal&_de=0&_ca=0&_ch=0&_da=0.

Только представьте, что приведенная выше строка имеется в некотором приложении! В качестве инструмента обновления URI указывает Meerkat выдать нам все текстовые блоки из категории Linux, которые были зарегистрированы за последний час, используя минимальную конфигурацию. Мы хотим еще более ограничить информацию, поступающую в результате исключения полей, содержащих описание, категорию, канал и данные. Давайте продублируем эту функциональную возможность с помощью xmlrpclib.

Объявите список параметров, создавая словарь языка Python (такой же, как структура в XML-RPC):


>>> params = {
... 'category' : 7,
... 'time_period' : '1HOUR',
... 'descriptions' : 0,
... 'categories' : 0,
... 'channels' : 0,
... 'dates' : 0
}


Первые два параметра определяют спектр нужной нам информации. Последние четыре - работают как переключатели, отключающие различные возвращенные компоненты. Далее, для получения необходимой информации мы вызовем некоторый метод сервера:


>>> results = meerkatsvr.meerkat.getItems(params)

Это выражение возвращает список словарей, содержащий одновременно заголовок и HTML-ссылку на все статьи Linux, появлявшиеся в Meerkat за последний час. Если ваш запрос возвращает пустой список, увеличьте время ожидания (например, до двух часов (2HOUR) или одного дня (1DAY)).

Теперь давайте пройдемся по этому списку и построим законченную HTML-ссылку на эти статьи:


>>> for d in results:
... print <A HREF=%s>%s</A> % (d[link],d[title])

Что мы получили

Этот подход дал нам некоторые преимущества. Мы улучшили читаемость кода. Кода стало меньше. Отделение представления от данных позволило вам легко выбрать альтернативу. Лучше всего то, что этот подход абсолютно в духе языка Python. Благодаря функциональным возможностям, встроенным в XML-RPC и xmlrpclib, ответ Meerkat сегодня представляет собой данные на языке Python, обладающие всей соответствующей гибкостью: делайте с ними что хотите, сохраняйте их в базе данных, показывайте в wxPython или в Tkinter. Или даже отсылайте другому клиенту через XML-RPC!