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 Authentication:
http://user:pass@host:port/path. Частьuser:passбудет закодирована в base64 как заголовок HTTP «Authorization» и отправлена на удалённый сервер в рамках процесса подключения при вызове метода XML-RPC. Вам нужно использовать это только в том случае, если удалённый сервер требует пользователя и пароль для HTTP Basic Authentication. Если указан 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
-
Официальная спецификация.
- Неофициальные исправления XML-RPC
-
«Неофициальные исправления» Фредрика Лундха, призванные прояснить некоторые детали в спецификации XML-RPC, а также указать «лучшие практики» при разработке собственных реализаций XML-RPC.
Объекты 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)))
Объекты 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"))
Объекты Binary
-
class xmlrpc.client.Binary -
Этот класс можно инициализировать данными типа bytes (которые могут включать символы NUL). Основной доступ к содержимому объекта
Binaryпредоставляется через атрибут:-
data -
Бинарные данные, инкапсулированные экземпляром
Binary. Данные предоставляются как объектbytes.
Объекты
Binaryимеют следующие методы, поддерживаемые в основном для внутреннего использования кодом маршализации/демаршализации:-
decode(bytes) -
Принимает объект base64
bytesи декодирует его как новые данные экземпляра.
-
encode(out) -
Записывает кодировку base 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)
Объекты Fault
-
class xmlrpc.client.Fault -
Объект
Faultинкапсулирует содержимое тега XML-RPC ошибки. Объекты 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)
Объекты 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)
Объекты 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))
Удобные функции
-
xmlrpc.client.dumps(params, methodname=None, methodresponse=None, encoding=None, allow_none=False) -
Преобразовать params в запрос XML-RPC или в ответ, если methodresponse имеет значение true. params может быть кортежем аргументов или экземпляром исключения
Fault. Если methodresponse имеет значение true, может быть возвращено только одно значение, что означает, что params должен иметь длину 1. encoding, если указан, — кодировка, используемая в сгенерированном XML; по умолчанию используется UTF-8. Значение PythonNoneне может использоваться в стандартном XML-RPC; для использования его с помощью расширения укажите значение true для 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; по умолчанию этот флаг имеет значение false.Устаревший флаг use_datetime аналогичен флагу use_builtin_types, но применяется только к значениям даты/времени.
Изменено в версии 3.3: Добавлен флаг use_builtin_types.
Пример использования клиента
# 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))
Пример использования клиента и сервера
См. Пример SimpleXMLRPCServer.
Примечания
-
1 -
Этот подход впервые был представлен в обсуждении на xmlrpc.com.
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.7/library/xmlrpc.client.html