Spec-Zone.ru › Python 3.6

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 и внутренний HTTP Transport экземпляр в противном случае. Необязательный третий аргумент — кодировка, по умолчанию 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

boolean

bool

int, i1, i2, i4, i8 или biginteger

int в диапазоне от -2147483648 до 2147483647. Значения получают тег <int>.

double или float

float. Значения получают тег <double>.

string

str

array

list или tuple, содержащие совместимые элементы. Массивы возвращаются как lists.

struct

dict. Ключи должны быть строками, значения могут быть любым совместимым типом. Объекты пользовательских классов могут передаваться; передается только атрибут __dict__.

dateTime.iso8601

DateTime или datetime.datetime. Возвращаемый тип зависит от значений флагов use_builtin_types и use_datetime.

base64

Binary, bytes или bytearray. Возвращаемый тип зависит от значения флага use_builtin_types.

nil

Константа None. Передача разрешена только если allow_none имеет значение true.

bigdecimal

decimal.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 для описания.

END_OF_DOCUMENT_MARKER

См. также

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 обеспечивается атрибутом:

data

Бинарные данные, заключенные в экземпляр Binary. Данные предоставляются как объект bytes.

Объекты 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

Объект Fault encapsulates 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. Значение Python None не может использоваться в стандартном 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API