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 booleanboolintилиi4intв диапазоне от -2147483648 до 2147483647.doublefloatstringstrarraylistилиtupleсодержащие совместимые элементы. Массивы возвращаются какlists.structdict. Ключи должны быть строками, значения могут быть любого совместимого типа. Объекты пользовательских классов могут быть переданы; передается только атрибут__dict__.dateTime.iso8601DateTimeилиdatetime.datetime. Тип возвращаемых данных зависит от значений флагов use_builtin_types и use_datetime.base64Binary,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, указывающим на ошибку.
Серверы, поддерживающие 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. Значение 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.
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