xmlrpclib — Доступ к клиенту XML-RPC
Примечание
Модуль xmlrpclib был переименован в xmlrpc.client в Python 3. Инструмент 2to3 автоматически адаптирует импорты при преобразовании ваших исходных кодов в Python 3.
Новое в версии 2.2.
Исходный код: Lib/xmlrpclib.py
XML-RPC — это метод удаленного вызова процедур, который использует XML, передаваемый через HTTP(S), в качестве транспорта. С его помощью клиент может вызывать методы с параметрами на удалённом сервере (сервер определяется URI) и получать обратно структурированные данные. Этот модуль поддерживает написание кода клиента XML-RPC; он обрабатывает все детали преобразования между согласованными объектами Python и XML в сети.
Предупреждение
Модуль xmlrpclib не защищен от данных, злонамеренно сконструированных для атак. Если вам нужно обработать недоверенные или неаутентифицированные данные, обратитесь к Уязвимости XML.
Изменено в версии 2.7.9: Для HTTPS-URI, xmlrpclib теперь по умолчанию выполняет все необходимые проверки сертификата и имени хоста.
-
class xmlrpclib.ServerProxy(uri[, transport[, encoding[, verbose[, allow_none[, use_datetime[, context]]]]]]) -
Экземпляр
ServerProxy— это объект, управляющий общением с удалённым сервером XML-RPC. Требуемый первый аргумент — URI (указатель ресурса), обычно URL сервера. Необязательный второй аргумент — экземпляр фабрики транспорта; по умолчанию он является внутренним экземпляромSafeTransportдля HTTPS-URL и внутренним экземпляром HTTPTransportв противном случае. Необязательный третий аргумент — кодировка, по умолчанию UTF-8. Необязательный четвёртый аргумент — флаг отладки.Следующие параметры управляют использованием возвращенного прокси-объекта. Если allow_none имеет значение true, Python-константа
Noneбудет преобразована в XML; по умолчанию, при значенииNoneгенерируется исключениеTypeError. Это часто используемое расширение спецификации XML-RPC, но не поддерживается всеми клиентами и серверами; см. http://ontosys.com/xml-rpc/extensions.php для описания. Флаг use_datetime может быть использован для представления значений даты/времени как объектовdatetime.datetime; по умолчанию он равен false. Объектыdatetime.datetimeмогут быть переданы в вызовы.Как HTTP, так и HTTPS-транспорты поддерживают расширение синтаксиса URL для HTTP Basic Authentication:
http://user:pass@host:port/path. Частьuser:passбудет закодирована в base64 как заголовок HTTP ‘Authorization’ и отправлена на удалённый сервер в процессе подключения при вызове метода XML-RPC. Вам нужно использовать это только в случае, если удалённый сервер требует пользователя и пароль для Basic Authentication. Если предоставлен HTTPS-URL, context может бытьssl.SSLContextи настраивает настройки SSL для базового HTTPS-соединения.Возвращаемый экземпляр — это прокси-объект с методами, которые можно использовать для вызова соответствующих вызовов RPC на удалённом сервере. Если удалённый сервер поддерживает API интроспекции, прокси можно также использовать для запроса у удалённого сервера поддерживаемых им методов (обнаружение сервисов) и получения других метаданных, связанных с сервером.
Совместимые типы (например, те, которые могут быть обработаны через XML), включают в себя следующие (и, за исключением отмеченных случаев, они демаршализуются как тот же тип Python):
Тип XML-RPC
Тип Python
booleanintилиi4doublestringarraylistилиtuple, содержащий совместимые элементы. Массивы возвращаются какlists.structdict. Ключи должны быть строками, значения могут быть любого совместимого типа. Объекты пользовательских классов могут быть переданы; передаётся только их атрибут__dict__.dateTime.iso8601DateTimeилиdatetime.datetime. Возвращаемый тип зависит от значений флагов use_datetime.base64nilКонстанта
None. Передача разрешена только если allow_none имеет значение true.Это полный набор типов данных, поддерживаемых XML-RPC. Вызовы методов также могут генерировать специальный экземпляр
Fault, используемый для сигнализации об ошибках сервера XML-RPC, илиProtocolError, используемый для сигнализации об ошибке в транспортном слое HTTP/HTTPS. ОбаFaultиProtocolErrorнаследуются от базового классаError. Обратите внимание, что, хотя начиная с Python 2.2, вы можете наследоваться от встроенных типов, модуль xmlrpclib в настоящее время не маршаллирует экземпляры таких подклассов.При передаче строк символы, специальные для XML, такие как
<,>, и&будут автоматически экранированы. Однако, ответственность за обеспечение отсутствия в строке символов, не разрешенных в XML, таких как управляющие символы с ASCII-кодами от 0 до 31 (кроме, конечно, табуляции, новой строки и возврата каретки), лежит на вызывающей стороне; если этого не сделать, запрос XML-RPC не будет корректным XML. Если вам необходимо передавать произвольные строки через XML-RPC, используйте класс-обёрткуBinary, описанный ниже.Serverсохраняется как псевдоним дляServerProxyдля обеспечения обратной совместимости. Новый код должен использоватьServerProxy.Изменено в версии 2.5: Добавлен флаг use_datetime.
Изменено в версии 2.6: Экземпляры новых классов могут быть переданы, если у них есть атрибут __dict__ и у них нет базового класса, который маршаллируется специальным образом.
Изменено в версии 2.7.9: Добавлен аргумент context.
См. также
- XML-RPC HOWTO
-
Хорошее описание работы XML-RPC и клиентского программного обеспечения на нескольких языках. Содержит практически всё, что нужно разработчику XML-RPC клиента.
- XML-RPC Introspection
-
Описание расширения протокола XML-RPC для интроспекции.
- Спецификация XML-RPC
-
Официальная спецификация.
- Неофициальные исправления XML-RPC
-
«Неофициальные исправления» Фредрика Лундха, предназначенные для уточнения определённых деталей в спецификации XML-RPC, а также для подсказок по «лучшим практикам» при разработке собственных реализаций XML-RPC.
1. Объекты ServerProxy
Экземпляр ServerProxy имеет метод, соответствующий каждому удалённому вызову процедуры, принимаемому сервером XML-RPC. Вызов метода выполняет RPC, определяемый по имени и сигнатуре аргумента (например, одно и то же имя метода может быть перегружено несколькими сигнатурами аргументов). RPC завершается возвращением значения, которое может быть либо возвращаемыми данными в соответствии с типом, либо объектом Fault или ProtocolError, указывающим на ошибку.
Серверы, поддерживающие API XML-интроспекции, поддерживают некоторые общие методы, сгруппированные под зарезервированным атрибутом system:
-
ServerProxy.system.listMethods() -
Этот метод возвращает список строк, по одной для каждого (несистемного) метода, поддерживаемого сервером XML-RPC.
-
ServerProxy.system.methodSignature(name) -
Этот метод принимает один параметр — имя метода, реализованного сервером XML-RPC. Он возвращает массив возможных сигнатур для этого метода. Сигнатура — это массив типов. Первый из этих типов — тип возвращаемого значения метода, остальные — параметры.
Поскольку разрешено несколько сигнатур (т. е. перегрузка), этот метод возвращает список сигнатур, а не одиночный элемент.
Сами сигнатуры ограничены верхним уровнем параметров, ожидаемых методом. Например, если метод ожидает один массив структур в качестве параметра и возвращает строку, его сигнатура — просто «строка, массив». Если он ожидает три целых числа и возвращает строку, его сигнатура — «строка, целое число, целое число, целое число».
Если для метода не определена никакая сигнатура, возвращается значение, не являющееся массивом. В Python это означает, что тип возвращаемого значения будет чем-то иным, кроме списка.
-
ServerProxy.system.methodHelp(name) -
Этот метод принимает один параметр — имя метода, реализованного сервером XML-RPC. Он возвращает строку документации, описывающую использование этого метода. Если такая строка недоступна, возвращается пустая строка. Строка документации может содержать разметку HTML.
2. Объекты Boolean
Этот класс может быть инициализирован любым значением Python; возвращаемый экземпляр зависит только от его истинностного значения. Он поддерживает различные операторы Python через методы __cmp__(), __repr__(), __int__() и __nonzero__(), все они реализованы очевидным образом.
Он также имеет следующий метод, поддерживаемый в основном для внутреннего использования кодом разбора:
-
Boolean.encode(out) -
Записать XML-RPC кодирование этого элемента Boolean в объект выходного потока.
Ниже приведён рабочий пример. Код сервера:
import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
def is_even(n):
return n % 2 == 0
server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_function(is_even, "is_even")
server.serve_forever()
Код клиента для предыдущего сервера:
import xmlrpclib
proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
print "3 is even: %s" % str(proxy.is_even(3))
print "100 is even: %s" % str(proxy.is_even(100))
3. Объекты DateTime
-
class xmlrpclib.DateTime -
Этот класс может быть инициализирован количеством секунд с начала эпохи, кортежем времени, строкой времени/даты в формате ISO 8601 или экземпляром
datetime.datetime. У него есть следующие методы, поддерживаемые в основном для внутреннего использования кодом сериализации/десериализации:-
decode(string) -
Принять строку в качестве нового значения времени экземпляра.
-
encode(out) -
Записать XML-RPC кодирование этого элемента
DateTimeв объект потока out.
Он также поддерживает некоторые встроенные операторы Python через методы
__cmp__()и__repr__(). -
Ниже приведён рабочий пример. Код сервера:
import datetime
from SimpleXMLRPCServer import SimpleXMLRPCServer
import xmlrpclib
def today():
today = datetime.datetime.today()
return xmlrpclib.DateTime(today)
server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_function(today, "today")
server.serve_forever()
Код клиента для предыдущего сервера:
import xmlrpclib
import datetime
proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
today = proxy.today()
# convert the ISO8601 string to a datetime object
converted = datetime.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S")
print "Today: %s" % converted.strftime("%d.%m.%Y, %H:%M")
4. Объекты Binary
-
class xmlrpclib.Binary -
Этот класс может быть инициализирован данными строки (которые могут включать символы NULL). Основной доступ к содержимому объекта
Binaryобеспечивается атрибутом:-
data -
Бинарные данные, инкапсулированные экземпляром
Binary. Данные предоставляются в виде 8-битной строки.
Объекты
Binaryимеют следующие методы, поддерживаемые в основном для внутреннего использования кодом сериализации/десериализации:-
decode(string) -
Принять строку base64 и декодировать её как новые данные экземпляра.
-
encode(out) -
Записать XML-RPC кодирование base 64 этого двоичного элемента в объект потока out.
Закодированные данные будут иметь новые строки каждые 76 символов в соответствии с RFC 2045 раздел 6.8, что было фактическим стандартом спецификации base64 при написании спецификации XML-RPC.
Он также поддерживает некоторые встроенные операторы Python через метод
__cmp__(). -
Пример использования двоичных объектов. Мы собираемся передать изображение по XMLRPC:
from SimpleXMLRPCServer import SimpleXMLRPCServer
import xmlrpclib
def python_logo():
with open("python_logo.jpg", "rb") as handle:
return xmlrpclib.Binary(handle.read())
server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_function(python_logo, 'python_logo')
server.serve_forever()
Клиент получает изображение и сохраняет его в файл:
import xmlrpclib
proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
with open("fetched_python_logo.jpg", "wb") as handle:
handle.write(proxy.python_logo().data)
5. Объекты Fault
-
class xmlrpclib.Fault -
Объект
Faultинкапсулирует содержимое тега XML-RPC fault. Объекты Fault имеют следующие атрибуты:-
faultCode -
Строка, указывающая тип ошибки.
-
faultString -
Строка, содержащая диагностическое сообщение, связанное с ошибкой.
-
В следующем примере мы намеренно вызовем Fault, вернув объект сложного типа. Код сервера:
from SimpleXMLRPCServer import SimpleXMLRPCServer
# A marshalling error is going to occur because we're returning a
# complex number
def add(x, y):
return x+y+0j
server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_function(add, 'add')
server.serve_forever()
Код клиента для предыдущего сервера:
import xmlrpclib
proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
try:
proxy.add(2, 5)
except xmlrpclib.Fault as err:
print "A fault occurred"
print "Fault code: %d" % err.faultCode
print "Fault string: %s" % err.faultString
6. Объекты ProtocolError
-
class xmlrpclib.ProtocolError -
Объект
ProtocolErrorописывает ошибку протокола в базовом уровне транспорта (например, ошибку 404 «не найдено», если сервер, указанный в URI, не существует). У него есть следующие атрибуты:-
url -
URI или URL, вызвавший ошибку.
-
errcode -
Код ошибки.
-
errmsg -
Сообщение об ошибке или диагностическая строка.
-
headers -
Строка, содержащая заголовки HTTP/HTTPS запроса, вызвавшего ошибку.
-
В следующем примере мы намеренно вызовем ProtocolError, указав URI, который не указывает на сервер XMLRPC:
import xmlrpclib
# create a ServerProxy with a URI that doesn't respond to XMLRPC requests
proxy = xmlrpclib.ServerProxy("http://www.google.com/")
try:
proxy.some_method()
except xmlrpclib.ProtocolError as err:
print "A protocol error occurred"
print "URL: %s" % err.url
print "HTTP/HTTPS headers: %s" % err.headers
print "Error code: %d" % err.errcode
print "Error message: %s" % err.errmsg
7. Объекты MultiCall
Новое в версии 2.4.
Объект MultiCall предоставляет способ инкапсуляции нескольких вызовов удалённого сервера в один запрос 1.
-
class xmlrpclib.MultiCall(server) -
Создать объект, используемый для группировки вызовов методов. server — конечная цель вызова. Вызовы могут быть сделаны к объекту результата, но они немедленно вернут
None, и только сохранят имя и параметры вызова в объектеMultiCall. Вызов самого объекта приводит к передаче всех сохранённых вызовов как одного запросаsystem.multicall. Результатом этого вызова является генератор; итерация по этому генератору приводит к получению отдельных результатов.
Пример использования этого класса. Код сервера:
from SimpleXMLRPCServer import SimpleXMLRPCServer
def add(x,y):
return x+y
def subtract(x, y):
return x-y
def multiply(x, y):
return x*y
def divide(x, y):
return x/y
# A simple server with simple arithmetic functions
server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_multicall_functions()
server.register_function(add, 'add')
server.register_function(subtract, 'subtract')
server.register_function(multiply, 'multiply')
server.register_function(divide, 'divide')
server.serve_forever()
Код клиента для предыдущего сервера:
import xmlrpclib
proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
multicall = xmlrpclib.MultiCall(proxy)
multicall.add(7,3)
multicall.subtract(7,3)
multicall.multiply(7,3)
multicall.divide(7,3)
result = multicall()
print "7+3=%d, 7-3=%d, 7*3=%d, 7/3=%d" % tuple(result)
8. Вспомогательные функции
-
xmlrpclib.boolean(value) -
Преобразовать любое значение Python в одно из констант XML-RPC Boolean,
TrueилиFalse.
-
xmlrpclib.dumps(params[, methodname[, methodresponse[, encoding[, allow_none]]]]) -
Преобразовать params в запрос XML-RPC или в ответ, если methodresponse истинно. params может быть либо кортежем аргументов, либо экземпляром исключения
Fault. Если methodresponse истинно, может быть возвращено только одно значение, что означает, что params должен иметь длину 1. encoding, если задан, — это кодировка, используемая в генерируемом XML; по умолчанию используется UTF-8. Значение PythonNoneне может использоваться в стандартном XML-RPC; для возможности его использования через расширение, укажите истинное значение для allow_none.
-
xmlrpclib.loads(data[, use_datetime]) -
Преобразовать запрос или ответ XML-RPC в объекты Python,
(params, methodname). params — кортеж аргументов; methodname — строка илиNoneесли имя метода отсутствует в пакете. Если пакет XML-RPC представляет собой ошибку, эта функция вызовет исключениеFault. Флаг use_datetime можно использовать для того, чтобы значения даты/времени представлялись как объектыdatetime.datetime; по умолчанию он ложный.Изменено в версии 2.5: Добавлен флаг use_datetime.
9. Пример использования клиента
# simple test program (from the XML-RPC specification)
from xmlrpclib import ServerProxy, Error
# server = ServerProxy("http://localhost:8000") # local server
server = ServerProxy("http://betty.userland.com")
print server
try:
print server.examples.getStateName(41)
except Error as v:
print "ERROR", v
Для доступа к серверу XML-RPC через HTTP-прокси необходимо определить пользовательский транспорт. Следующий пример показывает, как это сделать:
import xmlrpclib, httplib
class ProxiedTransport(xmlrpclib.Transport):
def set_proxy(self, proxy):
self.proxy = proxy
def make_connection(self, host):
self.realhost = host
h = httplib.HTTPConnection(self.proxy)
return h
def send_request(self, connection, handler, request_body):
connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler))
def send_host(self, connection, host):
connection.putheader('Host', self.realhost)
p = ProxiedTransport()
p.set_proxy('proxy-server:8080')
server = xmlrpclib.ServerProxy('http://time.xmlrpc.com/RPC2', transport=p)
print server.currentTime.getCurrentTime()
10. Пример использования клиента и сервера
См. Пример SimpleXMLRPCServer.
Примечания
-
1 -
Этот подход был впервые представлен в обсуждении на xmlrpc.com.
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/2.7/library/xmlrpclib.html