Документация Python неофициальный перевод

xmlrpc.client.md

409 строк · 29.1 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.4/library/xmlrpc.client.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 21.26. [`xmlrpc.client`](https://python-all.ru/3.4/library/xmlrpc.client.html#module-xmlrpc.client) – доступ к XML-RPC клиенту89**Исходный код:** [Lib/xmlrpc/client.py](https://python-all.ru/src/3.4/Lib/xmlrpc/client.py)1011---1213XML-RPC – это метод удаленного вызова процедур, использующий XML, передаваемый через HTTP в качестве tранспорта. С его помощью клиент может вызывать методы с параметрами на удаленном сервере (сервер задается URI) и получать структурированные данные. Этот модуль поддерживает написание клиентского кода XML-RPC; он обрабатывает все детали преобразования между совместимыми объектами Python и XML при передаче.1415> **Предупреждение**16>17> Модуль [`xmlrpc.client`](https://python-all.ru/3.4/library/xmlrpc.client.html#module-xmlrpc.client) не защищен от вредоносных данных. Если вам нужно разбирать непроверенные или неаутентифицированные данные, см. [*уязвимости XML*](https://python-all.ru/3.4/library/xml.html#xml-vulnerabilities).1819Изменено в версии 3.4.3: Для HTTPS URI модуль [`xmlrpc.client`](https://python-all.ru/3.4/library/xmlrpc.client.html#module-xmlrpc.client) теперь по умолчанию выполняет все необходимые проверки сертификата и имени хоста.2021#### `class xmlrpc.client.ServerProxy(uri, transport=None, encoding=None, verbose=False, allow_none=False, use_datetime=False, use_builtin_types=False, *, context=None)`2223Изменено в версии 3.3: Добавлен флаг *use\_builtin\_types*.2425Экземпляр [`ServerProxy`](https://python-all.ru/3.4/library/xmlrpc.client.html#xmlrpc.client.ServerProxy) – это объект, управляющий связью с удаленным XML-RPC сервером. Первый обязательный аргумент – URI (универсальный идентификатор ресурса), обычно это URL сервера. Второй необязательный аргумент – фабрика транспорта; по умолчанию это внутренний экземпляр `SafeTransport` для URL с https: и внутренний экземпляр HTTP `Transport` в противном случае. Третий необязательный аргумент – кодировка, по умолчанию UTF-8. Четвертый необязательный аргумент – флаг отладки. Если *allow\_none* истинно, константа Python `None` будет преобразована в XML; по умолчанию `None` вызывает исключение [`TypeError`](https://python-all.ru/3.4/library/exceptions.html#TypeError). Это часто используемое расширение спецификации XML-RPC, но оно поддерживается не всеми клиентами и серверами; описание см. на [http://ontosys.com/xml-rpc/extensions.php](https://python-all.ru/3.4/library/xmlrpc.client.html). Флаг *use\_builtin\_types* может использоваться для представления значений даты/времени как объектов [`datetime.datetime`](https://python-all.ru/3.4/library/datetime.html#datetime.datetime) и двоичных данных как объектов [`bytes`](https://python-all.ru/3.4/library/functions.html#bytes); по умолчанию этот флаг ложен. Объекты [`datetime.datetime`](https://python-all.ru/3.4/library/datetime.html#datetime.datetime) и [`bytes`](https://python-all.ru/3.4/library/functions.html#bytes) могут передаваться в вызовы.2627Устаревший флаг *use\_datetime* похож на *use\_builtin\_types*, но применяется только к значениям даты/времени.2829Транспорты HTTP и HTTPS поддерживают расширение синтаксиса URL для базовой аутентификации HTTP: `http://user:pass@host:port/path`. Часть `user:pass` будет закодирована в base64 как HTTP-заголовок «Authorization» и отправлена на удаленный сервер в процессе соединения при вызове метода XML-RPC. Это нужно использовать только в том случае, если удаленный сервер требует имя пользователя и пароль для базовой аутентификации. Если указан HTTPS URL, *context* может быть [`ssl.SSLContext`](https://python-all.ru/3.4/library/ssl.html#ssl.SSLContext) и настраивает параметры SSL базового HTTPS-соединения.3031Возвращаемый экземпляр – это прокси-объект с методами, которые можно использовать для вызова соответствующих RPC-вызовов на удалённом сервере. Если удалённый сервер поддерживает API интроспекции, прокси также можно использовать для запроса методов, которые он поддерживает (обнаружение служб), и получения других метаданных, связанных с сервером.3233Методы экземпляра [`ServerProxy`](https://python-all.ru/3.4/library/xmlrpc.client.html#xmlrpc.client.ServerProxy) принимают в качестве аргументов основные типы и объекты Python и возвращают основные типы и классы Python. Типы, которые являются совместимыми (т.е. могут быть преобразованы через XML), включают следующие (и, если не указано иное, они десериализуются в тот же тип Python):3435| Имя | Значение |36| --- | --- |37| `логическое значение` | Константы [`True`](https://python-all.ru/3.4/library/constants.html#True) и [`False`](https://python-all.ru/3.4/library/constants.html#False) |38| `целые числа` | Передаются напрямую |39| `с плавающей запятой числа` | Передаются напрямую |40| `строки` | Передаются напрямую |41| `массивы` | Любой тип последовательности Python, содержащий совместимые элементы. Массивы возвращаются как списки. |42| `структуры` | Словарь Python. Ключи должны быть строками, значения – любым совместимым типом. Можно передавать объекты пользовательских классов; передается только их атрибут *\_\_dict\_\_*. |43| `даты` | В секундах с начала эпохи. Передайте экземпляр класса `DateTime` или экземпляр [`datetime.datetime`](https://python-all.ru/3.4/library/datetime.html#datetime.datetime). |44| `двоичные данные` | Передайте экземпляр класса-обертки `Binary` или экземпляр [`bytes`](https://python-all.ru/3.4/library/functions.html#bytes). |4546Это полный набор типов данных, поддерживаемых XML-RPC. Вызовы методов также могут вызывать специальный экземпляр `Fault`, используемый для сигнализации ошибок XML-RPC сервера, или `ProtocolError`, используемый для сигнализации ошибки в транспортном слое HTTP/HTTPS. Оба `Fault` и `ProtocolError` наследуются от базового класса `Error`. Обратите внимание, что модуль xmlrpc.client в настоящее время не маршалирует экземпляры подклассов встроенных типов.4748При передаче строк символы, специальные для XML, такие как `<`, `>` и `&`, будут автоматически экранированы. Однако вызывающая сторона должна убедиться, что строка не содержит символов, запрещенных в XML, например управляющих символов с кодами ASCII от 0 до 31 (за исключением, конечно, табуляции, новой строки и возврата каретки); невыполнение этого требования приведет к XML-RPC запросу, который не является правильно оформленным XML. Если необходимо передать произвольные байты через XML-RPC, используйте класс [`bytes`](https://python-all.ru/3.4/library/functions.html#bytes) или класс-обертку *Binary*, описанный ниже.4950`Server` сохранен как псевдоним [`ServerProxy`](https://python-all.ru/3.4/library/xmlrpc.client.html#xmlrpc.client.ServerProxy) для обратной совместимости. В новом коде следует использовать [`ServerProxy`](https://python-all.ru/3.4/library/xmlrpc.client.html#xmlrpc.client.ServerProxy).5152Изменено в версии 3.4.3: Добавлен аргумент *context*.5354> **См. также**55>56> **[Руководство по XML-RPC](https://python-all.ru/3.4/library/xmlrpc.client.html)**57>58> Хорошее описание работы XML-RPC и клиентского ПО на нескольких языках. Содержит практически всё, что нужно знать разработчику XML-RPC клиента.59>60> **[Интроспекция XML-RPC](https://python-all.ru/3.4/library/xmlrpc.client.html)**61>62> Описывает расширение протокола XML-RPC для интроспекции.63>64> **[Спецификация XML-RPC](https://python-all.ru/3.4/library/xmlrpc.client.html)**65>66> Официальная спецификация.67>68> **[Неофициальные исправления XML-RPC](https://python-all.ru/3.4/library/xmlrpc.client.html)**69>70> «Неофициальные исправления» Фредрика Лунда, предназначенные для разъяснения некоторых деталей спецификации XML-RPC, а также для указания на «лучшие практики» при разработке собственных реализаций XML-RPC.7172## 21.26.1. Объекты ServerProxy7374Экземпляр [`ServerProxy`](https://python-all.ru/3.4/library/xmlrpc.client.html#xmlrpc.client.ServerProxy) имеет метод, соответствующий каждому удаленному вызову процедуры, принимаемому XML-RPC сервером. Вызов метода выполняет RPC, диспетчеризуемый по имени и сигнатуре аргументов (например, одно и то же имя метода может быть перегружено несколькими сигнатурами). RPC завершается возвратом значения, которое может быть либо возвращенными данными в совместимом типе, либо объектом `Fault` или `ProtocolError`, указывающим на ошибку.7576Серверы, поддерживающие XML introspection API, поддерживают некоторые общие методы, сгруппированные в зарезервированном атрибуте `system`:7778#### `ServerProxy.system.listMethods()`7980Этот метод возвращает список строк, по одной для каждого (не системного) метода, поддерживаемого XML-RPC сервером.8182#### `ServerProxy.system.methodSignature(name)`8384Этот метод принимает один параметр – имя метода, реализованного XML-RPC сервером. Он возвращает массив возможных сигнатур для этого метода. Сигнатура – это массив типов. Первый из этих типов – возвращаемый тип метода, остальные – параметры.8586Поскольку допускается несколько сигнатур (т.е. перегрузка), этот метод возвращает список сигнатур, а не один элемент.8788Сигнатуры ограничены параметрами верхнего уровня, ожидаемыми методом. Например, если метод ожидает один массив структур в качестве параметра и возвращает строку, его сигнатура – просто «string, array». Если он ожидает три целых числа и возвращает строку, его сигнатура – «string, int, int, int».8990Если для метода не определена сигнатура, возвращается не-массив. В Python это означает, что тип возвращаемого значения будет чем-то отличным от list.9192#### `ServerProxy.system.methodHelp(name)`9394Этот метод принимает один параметр – имя метода, реализованного XML-RPC сервером. Он возвращает строку документации, описывающую использование этого метода. Если такая строка отсутствует, возвращается пустая строка. Строка документации может содержать HTML-разметку.9596Далее следует работающий пример. Код сервера:9798```python99from xmlrpc.server import SimpleXMLRPCServer100101def is_even(n):102    return n%2 == 0103104server = SimpleXMLRPCServer(("localhost", 8000))105print("Listening on port 8000...")106server.register_function(is_even, "is_even")107server.serve_forever()108```109110Клиентский код для указанного сервера:111112```python113import xmlrpc.client114115proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")116print("3 is even: %s" % str(proxy.is_even(3)))117print("100 is even: %s" % str(proxy.is_even(100)))118```119120## 21.26.2. Объекты DateTime121122Этот класс может быть инициализирован секундами с начала эпохи, временным кортежем, строкой времени/даты в формате ISO 8601 или экземпляром [`datetime.datetime`](https://python-all.ru/3.4/library/datetime.html#datetime.datetime). Он имеет следующие методы, поддерживаемые в основном для внутреннего использования кодом маршалинга/демаршалинга:123124#### `DateTime.decode(string)`125126Принимает строку в качестве нового значения времени экземпляра.127128#### `DateTime.encode(out)`129130Записывает XML-RPC кодирование этого элемента `DateTime` в объект потока *out*.131132Он также поддерживает некоторые встроенные операторы Python через методы расширенного сравнения и [`__repr__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__repr__).133134Далее следует работающий пример. Код сервера:135136```python137import datetime138from xmlrpc.server import SimpleXMLRPCServer139import xmlrpc.client140141def today():142    today = datetime.datetime.today()143    return xmlrpc.client.DateTime(today)144145server = SimpleXMLRPCServer(("localhost", 8000))146print("Listening on port 8000...")147server.register_function(today, "today")148server.serve_forever()149```150151Клиентский код для указанного сервера:152153```python154import xmlrpc.client155import datetime156157proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")158159today = proxy.today()160# преобразует строку в формате ISO8601 в объект datetime161converted = datetime.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S")162print("Today: %s" % converted.strftime("%d.%m.%Y, %H:%M"))163```164165## 21.26.3. Объекты Binary166167Этот класс может быть инициализирован из данных bytes (которые могут содержать NUL). Основной доступ к содержимому объекта `Binary` предоставляется атрибутом:168169#### `Binary.data`170171Двоичные данные, инкапсулированные экземпляром `Binary`. Данные предоставляются в виде объекта [`bytes`](https://python-all.ru/3.4/library/functions.html#bytes).172173Объекты `Binary` имеют следующие методы, поддерживаемые в основном для внутреннего использования кодом маршалинга/демаршалинга:174175#### `Binary.decode(bytes)`176177Принимает объект base64 [`bytes`](https://python-all.ru/3.4/library/functions.html#bytes) и декодирует его как новые данные экземпляра.178179#### `Binary.encode(out)`180181Записывает XML-RPC base64-кодирование этого двоичного элемента в объект потока out.182183Закодированные данные будут содержать символы новой строки каждые 76 символов согласно [RFC 2045, раздел 6.8](https://python-all.ru/3.4/library/xmlrpc.client.html), что было фактическим стандартом спецификации base64 на момент написания спецификации XML-RPC.184185Он также поддерживает некоторые встроенные операторы Python через методы [`__eq__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__eq__) и [`__ne__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__ne__).186187Пример использования двоичных объектов. Мы собираемся передать изображение через XMLRPC:188189```python190from xmlrpc.server import SimpleXMLRPCServer191import xmlrpc.client192193def python_logo():194    with open("python_logo.jpg", "rb") as handle:195        return xmlrpc.client.Binary(handle.read())196197server = SimpleXMLRPCServer(("localhost", 8000))198print("Listening on port 8000...")199server.register_function(python_logo, 'python_logo')200201server.serve_forever()202```203204Клиент получает изображение и сохраняет его в файл:205206```python207import xmlrpc.client208209proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")210with open("fetched_python_logo.jpg", "wb") as handle:211    handle.write(proxy.python_logo().data)212```213214## 21.26.4. Объекты Fault215216Объект `Fault` инкапсулирует содержимое тега ошибки XML-RPC. Объекты Fault имеют следующие атрибуты:217218#### `Fault.faultCode`219220Строка, указывающая тип ошибки.221222#### `Fault.faultString`223224Строка, содержащая диагностическое сообщение, связанное с ошибкой.225226В следующем примере мы намеренно вызовем `Fault`, возвращая объект сложного типа. Код сервера:227228```python229from xmlrpc.server import SimpleXMLRPCServer230231# Произойдёт ошибка маршалинга, потому что возвращается232# комплексное число233def add(x,y):234    return x+y+0j235236server = SimpleXMLRPCServer(("localhost", 8000))237print("Listening on port 8000...")238server.register_function(add, 'add')239240server.serve_forever()241```242243Клиентский код для указанного сервера:244245```python246import xmlrpc.client247248proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")249try:250    proxy.add(2, 5)251except xmlrpc.client.Fault as err:252    print("A fault occurred")253    print("Fault code: %d" % err.faultCode)254    print("Fault string: %s" % err.faultString)255```256257## 21.26.5. Объекты ProtocolError258259Объект `ProtocolError` описывает ошибку протокола на уровне нижележащего транспорта (например, ошибка 404 «не найдено», если сервер, указанный в URI, не существует). Он имеет следующие атрибуты:260261#### `ProtocolError.url`262263URI или URL, вызвавший ошибку.264265#### `ProtocolError.errcode`266267Код ошибки.268269#### `ProtocolError.errmsg`270271Сообщение об ошибке или диагностическая строка.272273#### `ProtocolError.headers`274275Словарь (dict), содержащий заголовки HTTP/HTTPS-запроса, вызвавшего ошибку.276277В следующем примере мы намеренно вызовем `ProtocolError`, указав неверный URI:278279```python280import xmlrpc.client281282# создать ServerProxy с URI, который не отвечает на XMLRPC запросы283proxy = xmlrpc.client.ServerProxy("http://google.com/")284285try:286    proxy.some_method()287except xmlrpc.client.ProtocolError as err:288    print("A protocol error occurred")289    print("URL: %s" % err.url)290    print("HTTP/HTTPS headers: %s" % err.headers)291    print("Error code: %d" % err.errcode)292    print("Error message: %s" % err.errmsg)293```294295## 21.26.6. Объекты MultiCall296297Объект [`MultiCall`](https://python-all.ru/3.4/library/xmlrpc.client.html#xmlrpc.client.MultiCall) предоставляет способ инкапсулировать несколько вызовов удаленного сервера в один запрос [\[1\]](https://python-all.ru/3.4/library/xmlrpc.client.html#id6).298299#### `class xmlrpc.client.MultiCall(server)`300301Create an object used to boxcar method calls. *server* is the eventual target of the call. Calls can be made to the result object, but they will immediately return `None`, and only store the call name and parameters in the [`MultiCall`](https://python-all.ru/3.4/library/xmlrpc.client.html#xmlrpc.client.MultiCall) object. Calling the object itself causes all stored calls to be transmitted as a single `system.multicall` request. The result of this call is a [*generator*](https://python-all.ru/3.4/glossary.html#term-generator); iterating over this generator yields the individual results.302303Далее приведён пример использования этого класса. Серверный код:304305```python306from xmlrpc.server import SimpleXMLRPCServer307308def add(x, y):309    return x + y310311def subtract(x, y):312    return x - y313314def multiply(x, y):315    return x * y316317def divide(x, y):318    return x // y319320# Простой сервер с простыми арифметическими функциями321server = SimpleXMLRPCServer(("localhost", 8000))322print("Listening on port 8000...")323server.register_multicall_functions()324server.register_function(add, 'add')325server.register_function(subtract, 'subtract')326server.register_function(multiply, 'multiply')327server.register_function(divide, 'divide')328server.serve_forever()329```330331Клиентский код для указанного сервера:332333```python334import xmlrpc.client335336proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")337multicall = xmlrpc.client.MultiCall(proxy)338multicall.add(7, 3)339multicall.subtract(7, 3)340multicall.multiply(7, 3)341multicall.divide(7, 3)342result = multicall()343344print("7+3=%d, 7-3=%d, 7*3=%d, 7//3=%d" % tuple(result))345```346347## 21.26.7. Удобные функции348349#### `xmlrpc.client.dumps(params, methodname=None, methodresponse=None, encoding=None, allow_none=False)`350351Преобразует *params* в XML-RPC запрос или в ответ, если *methodresponse* истинно. *params* может быть либо кортежем аргументов, либо экземпляром класса исключения `Fault`. Если *methodresponse* истинно, может быть возвращено только одно значение, то есть *params* должен иметь длину 1. *encoding*, если указан, определяет кодировку, используемую в генерируемом XML; по умолчанию UTF-8. Значение [`None`](https://python-all.ru/3.4/library/constants.html#None) в Python не может использоваться в стандартном XML-RPC; чтобы разрешить его использование через расширение, передайте истинное значение для *allow\_none*.352353#### `xmlrpc.client.loads(data, use_datetime=False, use_builtin_types=False)`354355Преобразует XML-RPC запрос или ответ в объекты Python, `(params, methodname)`. *params* – кортеж аргументов; *methodname* – строка или `None`, если в пакете нет имени метода. Если XML-RPC пакет представляет условие ошибки, эта функция вызовет исключение `Fault`. Флаг *use\_builtin\_types* можно использовать, чтобы значения даты/времени представлялись как объекты [`datetime.datetime`](https://python-all.ru/3.4/library/datetime.html#datetime.datetime), а бинарные данные – как объекты [`bytes`](https://python-all.ru/3.4/library/functions.html#bytes); по умолчанию этот флаг равен false.356357Устаревший флаг *use\_datetime* похож на *use\_builtin\_types*, но применяется только к значениям даты/времени.358359Изменено в версии 3.3: Добавлен флаг *use\_builtin\_types*.360361## 21.26.8. Пример использования клиента362363```python364# простая тестовая программа (из спецификации XML-RPC)365from xmlrpc.client import ServerProxy, Error366367# server = ServerProxy("http://localhost:8000") # локальный сервер368server = ServerProxy("http://betty.userland.com")369370print(server)371372try:373    print(server.examples.getStateName(41))374except Error as v:375    print("ERROR", v)376```377378Для доступа к XML-RPC серверу через прокси необходимо определить собственный transport. Следующий пример показывает, как это сделать:379380```python381import xmlrpc.client, http.client382383class ProxiedTransport(xmlrpc.client.Transport):384    def set_proxy(self, proxy):385        self.proxy = proxy386    def make_connection(self, host):387        self.realhost = host388        h = http.client.HTTP(self.proxy)389        return h390    def send_request(self, connection, handler, request_body):391        connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler))392    def send_host(self, connection, host):393        connection.putheader('Host', self.realhost)394395p = ProxiedTransport()396p.set_proxy('proxy-server:8080')397server = xmlrpc.client.Server('http://time.xmlrpc.com/RPC2', transport=p)398print(server.currentTime.getCurrentTime())399```400401## 21.26.9. Пример использования клиента и сервера402403См. [*пример SimpleXMLRPCServer*](https://python-all.ru/3.4/library/xmlrpc.server.html#simplexmlrpcserver-example).404405Сноски406407| [\[1\]](https://python-all.ru/3.4/library/xmlrpc.client.html#id5) | Этот подход был впервые представлен в [обсуждении на xmlrpc.com](https://python-all.ru/3.4/library/xmlrpc.client.html). |408| --- | --- |409