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 теперь по умолчанию выполняет все необходимые проверки сертификатов и имени хоста.
Доступность: не Emscripten, не WASI.
Этот модуль не работает или недоступен на платформах WebAssembly wasm32-emscripten и wasm32-wasi. Для получения дополнительной информации см. платформы WebAssembly.
-
class xmlrpc.client.ServerProxy(uri, transport=None, encoding=None, verbose=False, allow_none=False, use_datetime=False, use_builtin_types=False, *, headers=(), context=None) -
Экземпляр
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могут передаваться в вызовы. Параметр headers — это необязательная последовательность HTTP-заголовков, которые необходимо отправлять с каждым запросом, представленная как последовательность пар из 2-х элементов, представляющих имя и значение заголовка. (например,[('Header-Name', 'value')]). Устаревший флаг use_datetime аналогичен use_builtin_types, но применяется только к значениям даты/времени.
Изменено в версии 3.3: Был добавлен флаг use_builtin_types.
Изменено в версии 3.8: Добавлен параметр headers.
Как транспорт HTTP, так и HTTPS поддерживают расширение синтаксиса URL для аутентификации HTTP Basic: http://user:pass@host:port/path. Часть user:pass будет закодирована в base64 в качестве заголовка HTTP ‘Authorization’ и отправлена на удаленный сервер в рамках процесса подключения при вызове метода XML-RPC. Вам нужно использовать это только если удаленный сервер требует пользователя и пароль для аутентификации Basic. Если предоставлен URL HTTPS, context может быть ssl.SSLContext и настраивает настройки SSL для подключение HTTPS.
Возвращаемый экземпляр — это объект-прокси с методами, которые можно использовать для вызова соответствующих вызовов RPC на удаленном сервере. Если удаленный сервер поддерживает API интроспекции, прокси также можно использовать для запроса у удаленного сервера поддерживаемых им методов (обнаружение сервиса) и извлечения других метаданных, связанных с сервером.
Типы, которые совместимы (например, которые могут быть сериализованы через XML), включают следующие (и за исключением случаев, когда это отмечено, они десериализуются как тот же тип Python):
Тип XML-RPC | Тип Python |
|---|---|
| |
|
|
|
|
| |
|
|
|
|
|
|
|
|
| Константа |
|
|
Это полный набор типов данных, поддерживаемых XML-RPC. Вызовы методов также могут вызвать специальный экземпляр Fault, используемый для сигнализации об ошибках сервера XML-RPC, или ProtocolError, используемый для сигнализации об ошибке в транспортном слое HTTP/HTTPS. Оба Fault и ProtocolError наследуются от базового класса, называемого Error. Обратите внимание, что модуль xmlrpc-клиента в настоящее время не сериализует экземпляры подклассов встроенных типов.
При передаче строк символы, являющиеся специальными для XML, такие как <, >, и &, будут автоматически экранироваться. Однако ответственность за обеспечение того, чтобы строка не содержала недопустимых в XML символов, таких как управляющие символы с кодами ASCII от 0 до 31 (за исключением, конечно, табуляции, новой строки и возврата каретки), лежит на вызывающей стороне; отсутствие таких проверок приведёт к некорректному 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. См. https://ws.apache.org/xmlrpc/types.html для описания.
См. также
- XML-RPC HOWTO
-
Хорошее описание работы XML-RPC и клиентского программного обеспечения на нескольких языках. Содержит практически всё, что нужно знать разработчику XML-RPC-клиента.
- XML-RPC Introspection
-
Описывает расширение протокола 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 через методы
rich comparisonи__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) -
Записывает XML-RPC кодировку base 64 этого двоичного элемента в объект потока out.
Закодированные данные будут содержать новые строки каждые 76 символов, в соответствии с RFC 2045 раздел 6.8, который был фактическим стандартом кодирования base64 на момент написания спецификации XML-RPC.
Он также поддерживает некоторые встроенные операторы Python через методы
__eq__()и__ne__(). -
Пример использования объектов binary. Мы собираемся передать изображение через 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 ‘not found’, если сервер, указанный в 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–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/library/xmlrpc.client.html