Spec-Zone.ru › Python 3.5

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 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
boolean bool
int или i4 int в диапазоне от -2147483648 до 2147483647.
double float
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.

Это полный набор типов данных, поддерживаемых 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.

См. также

XML-RPC HOWTO
Хорошее описание работы XML-RPC и клиентского программного обеспечения на разных языках. Содержит практически все, что нужно разработчику XML-RPC-клиента.
XML-RPC Introspection
Описание расширения протокола XML-RPC для интроспекции.
XML-RPC Specification
Официальная спецификация.
Неофициальные исправления XML-RPC
«Неофициальные исправления» Фредрика Лундха, предназначенные для уточнения определенных деталей спецификации XML-RPC, а также указания «лучших практик», которые следует использовать при разработке собственных реализаций XML-RPC.

1. Объекты ServerProxy

Экземпляр ServerProxy имеет метод, соответствующий каждому удаленному вызову процедуры, принимаемому сервером XML-RPC. Вызов метода выполняет RPC, который отправляется по имени и подписи аргумента (например, одно и то же имя метода может быть перегружено с помощью нескольких подписей аргументов). RPC завершается возвратом значения, которое может быть либо возвращаемыми данными в совместимом типе, либо объектом Fault или ProtocolError, указывающим на ошибку.

END_OF_DOCUMENT_MARKER

Серверы, поддерживающие 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)))

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"))

3. Объекты Binary

class xmlrpc.client.Binary

Этот класс может быть инициализирован данными типа bytes (которые могут включать нули). Основной доступ к содержимому объекта Binary предоставляется через атрибут:

data

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

Объекты Binary имеют следующие методы, в основном поддерживаемые для внутреннего использования кодом сериализации/десериализации:

decode(bytes)

Принимает объект base64 bytes и декодирует его как новые данные экземпляра.

encode(out)

Записывает base64 кодировку 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)

4. Объекты ошибок

class xmlrpc.client.Fault

Объект Fault инкапсулирует содержимое тега ошибки XML-RPC. Объекты ошибок имеют следующие атрибуты:

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)

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)

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))

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; для использования его через расширение, укажите значение True для allow_none.

END_OF_DOCUMENT_MARKER
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.

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))

9. Пример использования клиента и сервера

См. Пример SimpleXMLRPCServer.

Примечания

[1] Этот подход был впервые представлен в обсуждении на xmlrpc.com.

© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.5/library/xmlrpc.client.html

Spec-Zone.ru

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