xmlrpc.client.md
1> **Источник:** https://python-all.ru/3.2/library/xmlrpc.client.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 20.23. [`xmlrpc.client`](https://python-all.ru/3.2/library/xmlrpc.client.html#module-xmlrpc.client) – доступ к XML-RPC клиенту89**Исходный код:** [Lib/xmlrpc/client.py](https://python-all.ru/src/3.2/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.2/library/xmlrpc.client.html#module-xmlrpc.client) не защищён от вредоносных данных. Если необходимо анализировать непроверенные или неаутентифицированные данные, см. [*уязвимости XML*](https://python-all.ru/3.2/library/xml.html#xml-vulnerabilities).1819#### `class xmlrpc.client.ServerProxy(uri, transport=None, encoding=None, verbose=False, allow_none=False, use_datetime=False)`2021Экземпляр [`ServerProxy`](https://python-all.ru/3.2/library/xmlrpc.client.html#xmlrpc.client.ServerProxy) – это объект, управляющий взаимодействием с удалённым XML-RPC сервером. Обязательный первый аргумент – это URI (Uniform Resource Indicator), обычно это URL сервера. Второй необязательный аргумент – это экземпляр фабрики транспорта; по умолчанию это внутренний экземпляр `SafeTransport` для URL с https: и внутренний HTTP `Transport` в остальных случаях. Третий необязательный аргумент – это кодировка, по умолчанию UTF-8. Четвертый необязательный аргумент – флаг отладки. Если *allow\_none* истинно, то константа Python `None` будет преобразована в XML; по умолчанию `None` вызывает исключение [`TypeError`](https://python-all.ru/3.2/library/exceptions.html#TypeError). Это часто используемое расширение спецификации XML-RPC, но поддерживается не всеми клиентами и серверами; описание см. на [http://ontosys.com/xml-rpc/extensions.php](https://python-all.ru/3.2/library/xmlrpc.client.html). Флаг *use\_datetime* можно использовать, чтобы значения даты/времени представлялись как объекты [`datetime.datetime`](https://python-all.ru/3.2/library/datetime.html#datetime.datetime); по умолчанию он равен false. Объекты [`datetime.datetime`](https://python-all.ru/3.2/library/datetime.html#datetime.datetime) можно передавать в вызовы.2223Оба транспорта, HTTP и HTTPS, поддерживают расширение синтаксиса URL для HTTP базовой аутентификации: `http://user:pass@host:port/path`. Часть `user:pass` будет закодирована в base64 как HTTP-заголовок ‘Authorization’ и отправлена на удаленный сервер в процессе установки соединения при вызове метода XML-RPC. Использовать это нужно только в том случае, если удаленный сервер требует имя пользователя и пароль для базовой аутентификации.2425Возвращаемый экземпляр – это прокси-объект с методами, которые можно использовать для вызова соответствующих RPC-вызовов на удалённом сервере. Если удалённый сервер поддерживает API интроспекции, прокси также можно использовать для запроса методов, которые он поддерживает (обнаружение служб), и получения других метаданных, связанных с сервером.2627Методы экземпляра [`ServerProxy`](https://python-all.ru/3.2/library/xmlrpc.client.html#xmlrpc.client.ServerProxy) принимают в качестве аргументов основные типы и объекты Python и возвращают основные типы и классы Python. Типы, которые являются совместимыми (т.е. могут быть преобразованы через XML), включают следующие (и, если не указано иное, они десериализуются в тот же тип Python):2829| Имя | Значение |30| --- | --- |31| `логическое значение` | Константы [`True`](https://python-all.ru/3.2/library/constants.html#True) и [`False`](https://python-all.ru/3.2/library/constants.html#False) |32| `целые числа` | Передаются напрямую |33| `с плавающей запятой числа` | Передаются напрямую |34| `строки` | Передаются напрямую |35| `массивы` | Любой тип последовательности Python, содержащий совместимые элементы. Массивы возвращаются как списки. |36| `структуры` | Словарь Python. Ключи должны быть строками, значения – любым совместимым типом. Можно передавать объекты пользовательских классов; передается только их атрибут *\_\_dict\_\_*. |37| `даты` | в секундах с начала эпохи (передаётся экземпляр класса `DateTime`) или экземпляр [`datetime.datetime`](https://python-all.ru/3.2/library/datetime.html#datetime.datetime). |38| `двоичные данные` | передаётся экземпляр класса-обёртки `Binary` |3940Это полный набор типов данных, поддерживаемых XML-RPC. Вызовы методов также могут вызывать специальный экземпляр `Fault`, используемый для сигнализации ошибок XML-RPC сервера, или `ProtocolError`, используемый для сигнализации ошибки в транспортном слое HTTP/HTTPS. Оба `Fault` и `ProtocolError` наследуются от базового класса `Error`. Обратите внимание, что модуль xmlrpc.client в настоящее время не маршалирует экземпляры подклассов встроенных типов.4142При передаче строк символы, имеющие специальное значение в XML, такие как `<`, `>` и `&`, автоматически экранируются. Однако вызывающий код должен обеспечить, чтобы строка не содержала символов, недопустимых в XML, например, управляющих символов с ASCII-кодами от 0 до 31 (за исключением, разумеется, табуляции, перевода строки и возврата каретки); несоблюдение этого приведёт к XML-RPC запросу, который не является корректным XML. Если нужно передавать произвольные строки через XML-RPC, используйте класс-обёртку `Binary`, описанный ниже.4344`Server` сохранен как псевдоним [`ServerProxy`](https://python-all.ru/3.2/library/xmlrpc.client.html#xmlrpc.client.ServerProxy) для обратной совместимости. В новом коде следует использовать [`ServerProxy`](https://python-all.ru/3.2/library/xmlrpc.client.html#xmlrpc.client.ServerProxy).4546> **См. также**47>48> **[Руководство по XML-RPC](https://python-all.ru/3.2/library/xmlrpc.client.html)**49>50> Хорошее описание работы XML-RPC и клиентского ПО на нескольких языках. Содержит практически всё, что нужно знать разработчику XML-RPC клиента.51>52> **[Интроспекция XML-RPC](https://python-all.ru/3.2/library/xmlrpc.client.html)**53>54> Описывает расширение протокола XML-RPC для интроспекции.55>56> **[Спецификация XML-RPC](https://python-all.ru/3.2/library/xmlrpc.client.html)**57>58> Официальная спецификация.59>60> **[Неофициальные исправления XML-RPC](https://python-all.ru/3.2/library/xmlrpc.client.html)**61>62> «Неофициальные исправления» Фредрика Лунда, предназначенные для разъяснения некоторых деталей спецификации XML-RPC, а также для указания на «лучшие практики» при разработке собственных реализаций XML-RPC.6364## 20.23.1. Объекты ServerProxy6566Экземпляр [`ServerProxy`](https://python-all.ru/3.2/library/xmlrpc.client.html#xmlrpc.client.ServerProxy) имеет метод, соответствующий каждому удаленному вызову процедуры, принимаемому XML-RPC сервером. Вызов метода выполняет RPC, диспетчеризуемый по имени и сигнатуре аргументов (например, одно и то же имя метода может быть перегружено несколькими сигнатурами). RPC завершается возвратом значения, которое может быть либо возвращенными данными в совместимом типе, либо объектом `Fault` или `ProtocolError`, указывающим на ошибку.6768Серверы, поддерживающие XML introspection API, поддерживают некоторые общие методы, сгруппированные в зарезервированном атрибуте `system`:6970#### `ServerProxy.system.listMethods()`7172Этот метод возвращает список строк, по одной для каждого (не системного) метода, поддерживаемого XML-RPC сервером.7374#### `ServerProxy.system.methodSignature(name)`7576Этот метод принимает один параметр – имя метода, реализованного XML-RPC сервером. Он возвращает массив возможных сигнатур для этого метода. Сигнатура – это массив типов. Первый из этих типов – возвращаемый тип метода, остальные – параметры.7778Поскольку допускается несколько сигнатур (т.е. перегрузка), этот метод возвращает список сигнатур, а не один элемент.7980Сигнатуры ограничены параметрами верхнего уровня, ожидаемыми методом. Например, если метод ожидает один массив структур в качестве параметра и возвращает строку, его сигнатура – просто «string, array». Если он ожидает три целых числа и возвращает строку, его сигнатура – «string, int, int, int».8182Если для метода не определена сигнатура, возвращается не-массив. В Python это означает, что тип возвращаемого значения будет чем-то отличным от list.8384#### `ServerProxy.system.methodHelp(name)`8586Этот метод принимает один параметр – имя метода, реализованного XML-RPC сервером. Он возвращает строку документации, описывающую использование этого метода. Если такая строка отсутствует, возвращается пустая строка. Строка документации может содержать HTML-разметку.8788Далее следует работающий пример. Код сервера:8990```python91from xmlrpc.server import SimpleXMLRPCServer9293def is_even(n):94 return n%2 == 09596server = SimpleXMLRPCServer(("localhost", 8000))97print("Listening on port 8000...")98server.register_function(is_even, "is_even")99server.serve_forever()100```101102Клиентский код для указанного сервера:103104```python105import xmlrpc.client106107proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")108print("3 is even: %s" % str(proxy.is_even(3)))109print("100 is even: %s" % str(proxy.is_even(100)))110```111112## 20.23.2. Объекты DateTime113114Этот класс может быть инициализирован секундами с начала эпохи, временным кортежем, строкой времени/даты в формате ISO 8601 или экземпляром [`datetime.datetime`](https://python-all.ru/3.2/library/datetime.html#datetime.datetime). Он имеет следующие методы, поддерживаемые в основном для внутреннего использования кодом маршалинга/демаршалинга:115116#### `DateTime.decode(string)`117118Принимает строку в качестве нового значения времени экземпляра.119120#### `DateTime.encode(out)`121122Записывает XML-RPC кодирование этого элемента `DateTime` в объект потока *out*.123124Он также поддерживает некоторые встроенные операторы Python через методы расширенного сравнения и [`__repr__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__repr__).125126Далее следует работающий пример. Код сервера:127128```python129import datetime130from xmlrpc.server import SimpleXMLRPCServer131import xmlrpc.client132133def today():134 today = datetime.datetime.today()135 return xmlrpc.client.DateTime(today)136137server = SimpleXMLRPCServer(("localhost", 8000))138print("Listening on port 8000...")139server.register_function(today, "today")140server.serve_forever()141```142143Клиентский код для указанного сервера:144145```python146import xmlrpc.client147import datetime148149proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")150151today = proxy.today()152# преобразует строку в формате ISO8601 в объект datetime153converted = datetime.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S")154print("Today: %s" % converted.strftime("%d.%m.%Y, %H:%M"))155```156157## 20.23.3. Объекты Binary158159Этот класс может быть инициализирован строковыми данными (которые могут содержать NUL). Основной доступ к содержимому объекта `Binary` осуществляется через атрибут:160161#### `Binary.data`162163Двоичные данные, инкапсулированные экземпляром `Binary`. Данные предоставляются в виде 8-битной строки.164165Объекты `Binary` имеют следующие методы, поддерживаемые в основном для внутреннего использования кодом маршалинга/демаршалинга:166167#### `Binary.decode(string)`168169Принимает строку в base64 и декодирует её как новые данные экземпляра.170171#### `Binary.encode(out)`172173Записывает XML-RPC base64-кодирование этого двоичного элемента в объект потока out.174175Закодированные данные будут содержать символы новой строки каждые 76 символов согласно [RFC 2045, раздел 6.8](https://python-all.ru/3.2/library/xmlrpc.client.html), что было фактическим стандартом спецификации base64 на момент написания спецификации XML-RPC.176177Он также поддерживает некоторые встроенные операторы Python через методы [`__eq__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__eq__) и [`__ne__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__ne__).178179Пример использования двоичных объектов. Мы собираемся передать изображение через XMLRPC:180181```python182from xmlrpc.server import SimpleXMLRPCServer183import xmlrpc.client184185def python_logo():186 with open("python_logo.jpg", "rb") as handle:187 return xmlrpc.client.Binary(handle.read())188189server = SimpleXMLRPCServer(("localhost", 8000))190print("Listening on port 8000...")191server.register_function(python_logo, 'python_logo')192193server.serve_forever()194```195196Клиент получает изображение и сохраняет его в файл:197198```python199import xmlrpc.client200201proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")202with open("fetched_python_logo.jpg", "wb") as handle:203 handle.write(proxy.python_logo().data)204```205206## 20.23.4. Объекты Fault207208Объект `Fault` инкапсулирует содержимое тега ошибки XML-RPC. Объекты Fault имеют следующие атрибуты:209210#### `Fault.faultCode`211212Строка, указывающая тип ошибки.213214#### `Fault.faultString`215216Строка, содержащая диагностическое сообщение, связанное с ошибкой.217218В следующем примере мы намеренно вызовем `Fault`, возвращая объект сложного типа. Код сервера:219220```python221from xmlrpc.server import SimpleXMLRPCServer222223# Произойдёт ошибка маршалинга, потому что возвращается224# комплексное число225def add(x,y):226 return x+y+0j227228server = SimpleXMLRPCServer(("localhost", 8000))229print("Listening on port 8000...")230server.register_function(add, 'add')231232server.serve_forever()233```234235Клиентский код для указанного сервера:236237```python238import xmlrpc.client239240proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")241try:242 proxy.add(2, 5)243except xmlrpc.client.Fault as err:244 print("A fault occurred")245 print("Fault code: %d" % err.faultCode)246 print("Fault string: %s" % err.faultString)247```248249## 20.23.5. Объекты ProtocolError250251Объект `ProtocolError` описывает ошибку протокола на уровне нижележащего транспорта (например, ошибка 404 «не найдено», если сервер, указанный в URI, не существует). Он имеет следующие атрибуты:252253#### `ProtocolError.url`254255URI или URL, вызвавший ошибку.256257#### `ProtocolError.errcode`258259Код ошибки.260261#### `ProtocolError.errmsg`262263Сообщение об ошибке или диагностическая строка.264265#### `ProtocolError.headers`266267Словарь (dict), содержащий заголовки HTTP/HTTPS-запроса, вызвавшего ошибку.268269В следующем примере мы намеренно вызовем `ProtocolError`, указав неверный URI:270271```python272import xmlrpc.client273274# создать ServerProxy с URI, который не отвечает на XMLRPC запросы275proxy = xmlrpc.client.ServerProxy("http://google.com/")276277try:278 proxy.some_method()279except xmlrpc.client.ProtocolError as err:280 print("A protocol error occurred")281 print("URL: %s" % err.url)282 print("HTTP/HTTPS headers: %s" % err.headers)283 print("Error code: %d" % err.errcode)284 print("Error message: %s" % err.errmsg)285```286287## 20.23.6. Объекты MultiCall288289Объект [`MultiCall`](https://python-all.ru/3.2/library/xmlrpc.client.html#xmlrpc.client.MultiCall) предоставляет способ инкапсулировать несколько вызовов удаленного сервера в один запрос [\[1\]](https://python-all.ru/3.2/library/xmlrpc.client.html#id6).290291#### `class xmlrpc.client.MultiCall(server)`292293Create 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.2/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.2/glossary.html#term-generator); iterating over this generator yields the individual results.294295Пример использования этого класса приведён ниже. Код сервера296297```python298from xmlrpc.server import SimpleXMLRPCServer299300def add(x,y):301 return x+y302303def subtract(x, y):304 return x-y305306def multiply(x, y):307 return x*y308309def divide(x, y):310 return x/y311312# Простой сервер с простыми арифметическими функциями313server = SimpleXMLRPCServer(("localhost", 8000))314print("Listening on port 8000...")315server.register_multicall_functions()316server.register_function(add, 'add')317server.register_function(subtract, 'subtract')318server.register_function(multiply, 'multiply')319server.register_function(divide, 'divide')320server.serve_forever()321```322323Клиентский код для указанного сервера:324325```python326import xmlrpc.client327328proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")329multicall = xmlrpc.client.MultiCall(proxy)330multicall.add(7,3)331multicall.subtract(7,3)332multicall.multiply(7,3)333multicall.divide(7,3)334result = multicall()335336print("7+3=%d, 7-3=%d, 7*3=%d, 7/3=%d" % tuple(result))337```338339## 20.23.7. Удобные функции340341#### `xmlrpc.client.dumps(params, methodname=None, methodresponse=None, encoding=None, allow_none=False)`342343Преобразует *params* в XML-RPC запрос или в ответ, если *methodresponse* истинно. *params* может быть либо кортежем аргументов, либо экземпляром класса исключения `Fault`. Если *methodresponse* истинно, может быть возвращено только одно значение, то есть *params* должен иметь длину 1. *encoding*, если указан, определяет кодировку, используемую в генерируемом XML; по умолчанию UTF-8. Значение [`None`](https://python-all.ru/3.2/library/constants.html#None) в Python не может использоваться в стандартном XML-RPC; чтобы разрешить его использование через расширение, передайте истинное значение для *allow\_none*.344345#### `xmlrpc.client.loads(data, use_datetime=False)`346347Преобразует XML-RPC запрос или ответ в объекты Python, возвращая `(params, methodname)`. *params* – кортеж аргументов; *methodname* – строка или `None`, если имя метода отсутствует в пакете. Если XML-RPC пакет представляет собой условие ошибки, эта функция возбуждает исключение `Fault`. Флаг *use\_datetime* можно использовать, чтобы значения даты/времени представлялись как объекты [`datetime.datetime`](https://python-all.ru/3.2/library/datetime.html#datetime.datetime); по умолчанию он равен False.348349## 20.23.8. Пример использования клиента350351```python352# простая тестовая программа (из спецификации XML-RPC)353from xmlrpc.client import ServerProxy, Error354355# server = ServerProxy("http://localhost:8000") # локальный сервер356server = ServerProxy("http://betty.userland.com")357358print(server)359360try:361 print(server.examples.getStateName(41))362except Error as v:363 print("ERROR", v)364```365366Для доступа к XML-RPC серверу через прокси необходимо определить собственный transport. Следующий пример показывает, как это сделать:367368```python369import xmlrpc.client, http.client370371class ProxiedTransport(xmlrpc.client.Transport):372 def set_proxy(self, proxy):373 self.proxy = proxy374 def make_connection(self, host):375 self.realhost = host376 h = http.client.HTTP(self.proxy)377 return h378 def send_request(self, connection, handler, request_body):379 connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler))380 def send_host(self, connection, host):381 connection.putheader('Host', self.realhost)382383p = ProxiedTransport()384p.set_proxy('proxy-server:8080')385server = xmlrpc.client.Server('http://time.xmlrpc.com/RPC2', transport=p)386print(server.currentTime.getCurrentTime())387```388389## 20.23.9. Пример использования клиента и сервера390391См. [*пример SimpleXMLRPCServer*](https://python-all.ru/3.2/library/xmlrpc.server.html#simplexmlrpcserver-example).392393Сноски394395| [\[1\]](https://python-all.ru/3.2/library/xmlrpc.client.html#id5) | Этот подход был впервые представлен в [обсуждении на xmlrpc.com](https://python-all.ru/3.2/library/xmlrpc.client.html). |396| --- | --- |397