xmlrpc.client — Доступ к клиенту XML-RPC
Исходный код: Lib/xmlrpc/client.py
XML-RPC — это метод удаленного вызова процедур, который использует XML, передаваемый через HTTP(S) в качестве транспортного протокола. С его помощью клиент может вызывать методы с параметрами на удаленном сервере (сервер определяется URI) и получать обратно структурированные данные. Этот модуль поддерживает написание кода клиента XML-RPC; он обрабатывает все детали преобразования между совместимыми объектами Python и XML в сети.
Предупреждение
Модуль xmlrpc.client не защищен от злонамеренно сконструированных данных. Если вам нужно проанализировать недоверенные или неавторизованные данные, см. Уязвимости XML.
Изменено в версии 3.5: Для HTTPS-URI xmlrpc.client теперь по умолчанию выполняет все необходимые проверки сертификатов и имени хоста.
-
class xmlrpc.client.ServerProxy(uri, transport=None, encoding=None, verbose=False, allow_none=False, use_datetime=False, use_builtin_types=False, *, context=None) -
Изменено в версии 3.3: Добавлен флаг use_builtin_types.
Экземпляр
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_builtin_types можно использовать для того, чтобы значения даты/времени представлялись как объектыdatetime.datetime, а двоичные данные — как объектыbytes; этот флаг по умолчанию имеет значение false.datetime.datetime,bytesиbytearrayобъекты могут передаваться в вызовы. Устаревший флаг use_datetime аналогичен use_builtin_types, но применяется только к значениям даты/времени.Как HTTP, так и HTTPS-транспорты поддерживают расширение синтаксиса URL для аутентификации HTTP Basic:
http://user:pass@host:port/path. Частьuser:passбудет закодирована в base64 как заголовок HTTP ‘Authorization’ и отправлена на удаленный сервер в процессе подключения при вызове метода XML-RPC. Вам нужно использовать это только в том случае, если удаленный сервер требует пользователя и пароль аутентификации Basic. Если предоставлен HTTPS-URL, context может бытьssl.SSLContextи настраивает параметры SSL базового HTTPS-соединения.Возвращаемый экземпляр — это прокси-объект с методами, которые можно использовать для вызова соответствующих вызовов RPC на удаленном сервере. Если удаленный сервер поддерживает API интроспекции, прокси также можно использовать для запроса у удаленного сервера поддерживаемых им методов (обнаружение сервиса) и извлечения другой связанной с сервером метаданных.
Совместимые типы (например, те, которые могут быть закодированы через XML), включают следующее (за исключением отмеченных случаев, они распаковываются как тот же тип Python):
Тип XML-RPC
Тип Python
booleanint,i1,i2,i4,i8илиbigintegerintв диапазоне от -2147483648 до 2147483647. Значения получают тег<int>.doubleилиfloatfloat. Значения получают тег<double>.stringarraylistилиtuple, содержащие совместимые элементы. Массивы возвращаются какlists.structdict. Ключи должны быть строками, значения могут быть любым совместимым типом. Объекты пользовательских классов могут передаваться; передается только атрибут__dict__.dateTime.iso8601DateTimeилиdatetime.datetime. Возвращаемый тип зависит от значений флагов use_builtin_types и use_datetime.base64Binary,bytesилиbytearray. Возвращаемый тип зависит от значения флага use_builtin_types.nilКонстанта
None. Передача разрешена только если allow_none имеет значение true.bigdecimaldecimal.Decimal. Возвращаемый тип только.Это полный набор типов данных, поддерживаемых XML-RPC. Вызовы методов также могут возбудить специальный экземпляр
Fault, используемый для сигнализации об ошибках сервера XML-RPC, илиProtocolError, используемый для сигнализации об ошибке в транспортном слое HTTP/HTTPS. ОбаFaultиProtocolErrorнаследуются от базового класса, называемогоError. Обратите внимание, что модуль клиента xmlrpc в настоящее время не кодирует экземпляры подклассов встроенных типов.При передаче строк символы, особые для XML, такие как
<,>, и&будут автоматически экранированы. Однако ответственность вызывающей стороны заключается в обеспечении того, чтобы строка была свободна от символов, которые не допускаются в XML, таких как управляющие символы с ASCII-кодами от 0 до 31 (за исключением, конечно, табуляции, новой строки и возврата каретки); отсутствие этого приведет к тому, что запрос XML-RPC не будет правильно сформированным XML. Если вам нужно передавать произвольные байты через XML-RPC, используйте классыbytesилиbytearrayили оберточный классBinary, описанный ниже.Serverсохраняется как псевдоним дляServerProxyдля обратной совместимости. Новый код должен использоватьServerProxy.Изменено в версии 3.5: Добавлен аргумент context.
Изменено в версии 3.6: Добавлена поддержка тегов типов с префиксами (например,
ex:nil). Добавлен поддержка распаковки дополнительных типов, используемых реализацией Apache XML-RPC для чисел:i1,i2,i8,biginteger,floatиbigdecimal. См. http://ws.apache.org/xmlrpc/types.html для описания.
См. также
- XML-RPC HOWTO
-
Хорошее описание работы XML-RPC и клиентского программного обеспечения на нескольких языках. Содержит практически всё, что нужно знать разработчику XML-RPC клиента.
- XML-RPC Introspection
-
Описывает расширение протокола XML-RPC для интроспекции.
- XML-RPC Specification
-
Официальная спецификация.
- Неофициальные исправления XML-RPC
-
«Неофициальные исправления» Фредрика Лунда, предназначенные для уточнения определённых деталей в спецификации XML-RPC, а также указания «лучших практик» при проектировании собственных реализаций XML-RPC.
21.26.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 разметку.
Изменено в версии 3.5: Экземпляры ServerProxy поддерживают протокол менеджера контекста для закрытия базового транспорта.
Следующий пример демонстрирует работу. Код сервера:
from xmlrpc.server 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 xmlrpc.client
with xmlrpc.client.ServerProxy("http://localhost:8000/") as proxy:
print("3 is even: %s" % str(proxy.is_even(3)))
print("100 is even: %s" % str(proxy.is_even(100)))
21.26.2. Объекты DateTime
-
class xmlrpc.client.DateTime -
Этот класс может быть инициализирован количеством секунд с эпохи, кортежем времени, строкой времени/даты в формате ISO 8601 или экземпляром
datetime.datetime. Он имеет следующие методы, в основном используемые для внутренней работы кода сериализации/десериализации:-
decode(string) -
Принимает строку в качестве нового значения времени экземпляра.
-
encode(out) -
Записывает XML-RPC кодировку этого элемента
DateTimeв объект потока out.
Также поддерживает некоторые встроенные операторы Python через сравнение и методы
__repr__(). -
Следующий пример демонстрирует работу. Код сервера:
import datetime
from xmlrpc.server import SimpleXMLRPCServer
import xmlrpc.client
def today():
today = datetime.datetime.today()
return xmlrpc.client.DateTime(today)
server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
server.register_function(today, "today")
server.serve_forever()
Код клиента для предшествующего сервера:
import xmlrpc.client
import datetime
proxy = xmlrpc.client.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"))
21.26.3. Бинарные объекты
-
class xmlrpc.client.Binary -
Этот класс может быть инициализирован данными типа bytes (которые могут включать символы NUL). Основной доступ к содержимому объекта
Binaryобеспечивается атрибутом:Объекты
Binaryимеют следующие методы, в основном используемые для внутренней работы кода сериализации/десериализации:-
decode(bytes) -
Принимает базовый 64-битный объект
bytesи декодирует его как новые данные экземпляра.
-
encode(out) -
Записывает базовый 64-битный код XML-RPC этого бинарного элемента в объект потока out. Кодированные данные будут иметь новые строки каждые 76 символов в соответствии с RFC 2045, раздел 6.8, которая была фактическим стандартом кодирования base64 на момент написания спецификации XML-RPC.
Также поддерживает некоторые встроенные операторы Python через
__eq__()и__ne__()методы. -
Пример использования бинарных объектов. Мы собираемся передать изображение через XMLRPC:
from xmlrpc.server import SimpleXMLRPCServer
import xmlrpc.client
def python_logo():
with open("python_logo.jpg", "rb") as handle:
return xmlrpc.client.Binary(handle.read())
server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
server.register_function(python_logo, 'python_logo')
server.serve_forever()
Клиент получает изображение и сохраняет его в файл:
import xmlrpc.client
proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
with open("fetched_python_logo.jpg", "wb") as handle:
handle.write(proxy.python_logo().data)
21.26.4. Объекты Fault
-
class xmlrpc.client.Fault -
Объект
Faultencapsulates the content of an XML-RPC fault tag. Объекты Fault имеют следующие атрибуты:-
faultCode -
Строка, указывающая тип ошибки.
-
faultString -
Строка, содержащая сообщение об ошибке, связанное с ошибкой.
-
В следующем примере мы намеренно вызовем Fault, вернув объект сложного типа. Код сервера:
from xmlrpc.server 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 xmlrpc.client
proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
try:
proxy.add(2, 5)
except xmlrpc.client.Fault as err:
print("A fault occurred")
print("Fault code: %d" % err.faultCode)
print("Fault string: %s" % err.faultString)
21.26.5. Объекты ProtocolError
-
class xmlrpc.client.ProtocolError -
Объект
ProtocolErrorописывает ошибку протокола в базовом слое транспорта (например, ошибку 404 «не найдено», если сервер, указанный в URI, не существует). Он имеет следующие атрибуты:-
url -
URI или URL, вызвавший ошибку.
-
errcode -
Код ошибки.
-
errmsg -
Сообщение об ошибке или диагностическая строка.
-
headers -
Словарь, содержащий заголовки HTTP/HTTPS запроса, вызвавшего ошибку.
-
В следующем примере мы намеренно вызовем ProtocolError, предоставив недействительный URI:
import xmlrpc.client
# create a ServerProxy with a URI that doesn't respond to XMLRPC requests
proxy = xmlrpc.client.ServerProxy("http://google.com/")
try:
proxy.some_method()
except xmlrpc.client.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)
21.26.6. Объекты MultiCall
Объект MultiCall предоставляет способ инкапсуляции нескольких вызовов удалённого сервера в один запрос 1.
-
class xmlrpc.client.MultiCall(server) -
Создайте объект, используемый для группового вызова методов. server — конечный объект, на который направлен вызов. Вызовы могут быть выполнены с результатом объекта, но они будут немедленно возвращать
None, и только хранить имя вызова и параметры в объектеMultiCall. Вызов самого объекта приводит к передаче всех сохраненных вызовов как одногоsystem.multicallзапроса. Результатом этого вызова является генератор; итерация по этому генератору возвращает отдельные результаты.
Пример использования этого класса приводится ниже. Код сервера:
from xmlrpc.server 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 xmlrpc.client
proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
multicall = xmlrpc.client.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))
21.26.7. Удобные функции
-
xmlrpc.client.dumps(params, methodname=None, methodresponse=None, encoding=None, allow_none=False) -
Преобразует params в запрос XML-RPC или в ответ, если methodresponse истинно. params может быть кортежем аргументов или экземпляром исключения
Fault. Если methodresponse истинно, может быть возвращено только одно значение, что означает, что params должен иметь длину 1. encoding, если предоставлен, — это кодировка, используемая в сгенерированном XML; по умолчанию используется UTF-8. Значение PythonNoneне может использоваться в стандартном XML-RPC; чтобы разрешить его использование через расширение, укажите истинное значение для allow_none.
-
xmlrpc.client.loads(data, use_datetime=False, use_builtin_types=False) -
Преобразует запрос или ответ XML-RPC в объекты Python,
(params, methodname). params — это кортеж аргументов; methodname — строка илиNoneесли имя метода отсутствует в пакете. Если пакет XML-RPC представляет собой ошибку, эта функция вызовет исключениеFault. Флаг use_builtin_types может быть использован для представления значений даты/времени как объектовdatetime.datetime, а двоичных данных — как объектовbytes; по умолчанию этот флаг ложный.Устаревший флаг use_datetime аналогичен use_builtin_types, но применяется только к значениям даты/времени.
Изменено в версии 3.3: Добавлен флаг use_builtin_types.
21.26.8. Пример использования клиента
# simple test program (from the XML-RPC specification)
from xmlrpc.client import ServerProxy, Error
# server = ServerProxy("http://localhost:8000") # local server
with ServerProxy("http://betty.userland.com") as proxy:
print(proxy)
try:
print(proxy.examples.getStateName(41))
except Error as v:
print("ERROR", v)
Для доступа к серверу XML-RPC через HTTP-прокси необходимо определить пользовательский транспорт. Следующий пример демонстрирует, как это сделать:
import http.client
import xmlrpc.client
class ProxiedTransport(xmlrpc.client.Transport):
def set_proxy(self, host, port=None, headers=None):
self.proxy = host, port
self.proxy_headers = headers
def make_connection(self, host):
connection = http.client.HTTPConnection(*self.proxy)
connection.set_tunnel(host, headers=self.proxy_headers)
self._connection = host, connection
return connection
transport = ProxiedTransport()
transport.set_proxy('proxy-server', 8080)
server = xmlrpc.client.ServerProxy('http://betty.userland.com', transport=transport)
print(server.examples.getStateName(41))
21.26.9. Пример использования клиента и сервера
См. Пример SimpleXMLRPCServer.
Примечания
-
1 -
Этот подход впервые был представлен в обсуждении на xmlrpc.com.
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.6/library/xmlrpc.client.html