xmlrpc.client — XML-RPC-Client-Zugriff

Quellcode: Lib/xmlrpc/client.py


XML-RPC ist eine Remote Procedure Call-Methode, die XML über HTTP(S) als Transport verwendet. Damit kann ein Client Methoden mit Parametern bei einem entfernten Server aufrufen (der Server wird durch eine URI benannt) und strukturierte Daten zurückerhalten. Dieses Modul unterstützt das Schreiben von XML-RPC-Client-Code; es kümmert sich um alle Details der Übersetzung zwischen konformen Python-Objekten und XML im Netzwerk.

Warnung

Das Modul xmlrpc.client ist nicht gegen böswillig konstruierte Daten gesichert. Wenn Sie nicht vertrauenswürdige oder nicht authentifizierte Daten parsen müssen, siehe XML-Sicherheit.

Geändert in Version 3.5: Für HTTPS-URIs führt xmlrpc.client standardmäßig alle notwendigen Zertifikats- und Hostnamenprüfungen durch.

Verfügbarkeit: nicht WASI.

Dieses Modul funktioniert nicht oder ist nicht auf WebAssembly verfügbar. Weitere Informationen finden Sie unter WebAssembly-Plattformen.

class xmlrpc.client.ServerProxy(uri, transport=None, encoding=None, verbose=False, allow_none=False, use_datetime=False, use_builtin_types=False, *, headers=(), context=None)

Eine Instanz von ServerProxy ist ein Objekt, das die Kommunikation mit einem entfernten XML-RPC-Server verwaltet. Das erforderliche erste Argument ist eine URI (Uniform Resource Indicator) und normalerweise die URL des Servers. Das optionale zweite Argument ist eine Transport-Factory-Instanz; standardmäßig ist dies eine interne SafeTransport-Instanz für https:-URLs und andernfalls eine interne HTTP-Transport-Instanz. Das optionale dritte Argument ist eine Kodierung, standardmäßig UTF-8. Das optionale vierte Argument ist ein Debugging-Flag.

Die folgenden Parameter steuern die Verwendung der zurückgegebenen Proxy-Instanz. Wenn allow_none wahr ist, wird die Python-Konstante None in XML übersetzt; das Standardverhalten ist, dass None einen TypeError auslöst. Dies ist eine häufig verwendete Erweiterung der XML-RPC-Spezifikation, wird aber nicht von allen Clients und Servern unterstützt; siehe http://ontosys.com/xml-rpc/extensions.php für eine Beschreibung. Das Flag use_builtin_types kann verwendet werden, um Datums-/Zeitwerte als datetime.datetime-Objekte und Binärdaten als bytes-Objekte darzustellen; dieses Flag ist standardmäßig falsch. datetime.datetime, bytes und bytearray-Objekte können an Aufrufe übergeben werden. Der Parameter headers ist eine optionale Sequenz von HTTP-Headern, die mit jeder Anfrage gesendet werden sollen, ausgedrückt als Sequenz von 2-Tupeln, die den Header-Namen und -Wert darstellen. (z. B. [('Header-Name', 'wert')]). Wenn eine HTTPS-URL angegeben wird, kann context ein ssl.SSLContext sein und konfiguriert die SSL-Einstellungen der zugrunde liegenden HTTPS-Verbindung. Das veraltete Flag use_datetime ist ähnlich wie use_builtin_types, aber es gilt nur für Datums-/Zeitwerte.

Geändert in Version 3.3: Das Flag use_builtin_types wurde hinzugefügt.

Geändert in Version 3.8: Der Parameter headers wurde hinzugefügt.

Sowohl der HTTP- als auch der HTTPS-Transport unterstützen die URL-Syntaxerweiterung für HTTP Basic Authentication: http://user:pass@host:port/path. Der Teil user:pass wird als HTTP-‚Authorization‘-Header base64-codiert und während des Verbindungsprozesses beim Aufruf einer XML-RPC-Methode an den entfernten Server gesendet. Sie müssen dies nur verwenden, wenn der entfernte Server einen Basic Authentication-Benutzer und ein Passwort benötigt.

Die zurückgegebene Instanz ist ein Proxy-Objekt mit Methoden, die zum Aufrufen entsprechender RPC-Aufrufe auf dem entfernten Server verwendet werden können. Wenn der entfernte Server die Introspektions-API unterstützt, kann der Proxy auch verwendet werden, um den entfernten Server nach den unterstützten Methoden abzufragen (Service Discovery) und andere serverbezogene Metadaten abzurufen.

Typen, die konform sind (z. B. die durch XML gemarshallt werden können), umfassen die folgenden (und soweit nicht anders angegeben, werden sie als derselbe Python-Typ unmarhallt)

XML-RPC-Typ

Python Typ

boolean

bool

int, i1, i2, i4, i8 oder biginteger

int im Bereich von -2147483648 bis 2147483647. Werte erhalten das Tag <int>.

double oder float

float. Werte erhalten das Tag <double>.

string

str

array

list oder tuple mit konformen Elementen. Arrays werden als Listen zurückgegeben.

struct

dict. Schlüssel müssen Strings sein, Werte können beliebige konforme Typen sein. Objekte benutzerdefinierter Klassen können übergeben werden; nur ihr __dict__-Attribut wird übertragen.

dateTime.iso8601

DateTime oder datetime.datetime. Der zurückgegebene Typ hängt von den Werten der Flags use_builtin_types und use_datetime ab.

base64

Binary, bytes oder bytearray. Der zurückgegebene Typ hängt vom Wert des Flags use_builtin_types ab.

nil

Die Konstante None. Die Übergabe ist nur erlaubt, wenn allow_none wahr ist.

bigdecimal

decimal.Decimal. Nur zurückgegebener Typ.

Dies ist die vollständige Menge der von XML-RPC unterstützten Datentypen. Methodenaufrufe können auch eine spezielle Fault-Instanz auslösen, die zur Signalgebung von XML-RPC-Serverfehlern verwendet wird, oder ProtocolError, die zur Signalgebung eines Fehlers in der HTTP/HTTPS-Transportschicht verwendet wird. Sowohl Fault als auch ProtocolError leiten sich von einer Basisklasse namens Error ab. Beachten Sie, dass das xmlrpc-Client-Modul derzeit keine Instanzen von Unterklassen von eingebauten Typen marshallt.

Beim Übergeben von Strings werden XML-spezifische Zeichen wie <, > und & automatisch escaped. Es liegt jedoch in der Verantwortung des Aufrufers sicherzustellen, dass der String frei von Zeichen ist, die in XML nicht zulässig sind, wie z. B. Steuerzeichen mit ASCII-Werten zwischen 0 und 31 (außer Tabulator, Zeilenvorschub und Wagenrücklauf); andernfalls wird eine XML-RPC-Anfrage generiert, die kein wohlgeformtes XML ist. Wenn Sie beliebige Bytes über XML-RPC übergeben müssen, verwenden Sie die Klassen bytes oder bytearray oder die unten beschriebene Wrapper-Klasse Binary.

Server wird aus Gründen der Abwärtskompatibilität als Alias für ServerProxy beibehalten. Neuer Code sollte ServerProxy verwenden.

Geändert in Version 3.5: Das Argument context wurde hinzugefügt.

Geändert in Version 3.6: Unterstützung für Typ-Tags mit Präfixen (z. B. ex:nil) hinzugefügt. Unterstützung für das Unmarshalling zusätzlicher Typen, die von der Apache XML-RPC-Implementierung für Numeriken verwendet werden: i1, i2, i8, biginteger, float und bigdecimal. Siehe https://ws.apache.org/xmlrpc/types.html für eine Beschreibung.

Siehe auch

XML-RPC HOWTO

Eine gute Beschreibung der Funktionsweise von XML-RPC und Client-Software in mehreren Sprachen. Enthält so ziemlich alles, was ein XML-RPC-Client-Entwickler wissen muss.

XML-RPC-Introspektion

Beschreibt die XML-RPC-Protokollerweiterung für Introspektion.

XML-RPC-Spezifikation

Die offizielle Spezifikation.

ServerProxy-Objekte

Eine Instanz von ServerProxy hat eine Methode, die jedem vom XML-RPC-Server akzeptierten entfernten Prozeduraufruf entspricht. Der Aufruf der Methode führt einen RPC durch, der sowohl nach Name als auch nach Argument-Signatur aufgerufen wird (z. B. kann derselbe Methodenname mit mehreren Argument-Signaturen überladen werden). Der RPC endet mit der Rückgabe eines Wertes, der entweder zurückgegebene Daten in einem konformen Typ oder ein Fault- oder ProtocolError-Objekt sein kann, das einen Fehler signalisiert.

Server, die die XML-Introspektions-API unterstützen, unterstützen einige gängige Methoden, die unter dem reservierten Attribut system zusammengefasst sind

ServerProxy.system.listMethods()

Diese Methode gibt eine Liste von Strings zurück, eine für jede (Nicht-System-)Methode, die vom XML-RPC-Server unterstützt wird.

ServerProxy.system.methodSignature(name)

Diese Methode nimmt einen Parameter entgegen, den Namen einer vom XML-RPC-Server implementierten Methode. Sie gibt ein Array möglicher Signaturen für diese Methode zurück. Eine Signatur ist ein Array von Typen. Der erste dieser Typen ist der Rückgabetyp der Methode, die restlichen sind Parameter.

Da mehrere Signaturen (d. h. Überladung) zulässig sind, gibt diese Methode eine Liste von Signaturen anstelle eines einzelnen Werts zurück.

Signaturen selbst sind auf die Top-Level-Parameter beschränkt, die von einer Methode erwartet werden. Wenn eine Methode beispielsweise ein Array von Structs als Parameter erwartet und einen String zurückgibt, ist ihre Signatur einfach „string, array“. Wenn sie drei Integer erwartet und einen String zurückgibt, ist ihre Signatur „string, int, int, int“.

Wenn für die Methode keine Signatur definiert ist, wird ein Wert zurückgegeben, der kein Array ist. In Python bedeutet dies, dass der Typ des zurückgegebenen Werts etwas anderes als eine Liste ist.

ServerProxy.system.methodHelp(name)

Diese Methode nimmt einen Parameter entgegen, den Namen einer vom XML-RPC-Server implementierten Methode. Sie gibt einen Dokumentationsstring zurück, der die Verwendung dieser Methode beschreibt. Wenn keine solche Zeichenkette verfügbar ist, wird eine leere Zeichenkette zurückgegeben. Der Dokumentationsstring kann HTML-Markup enthalten.

Geändert in Version 3.5: Instanzen von ServerProxy unterstützen das Protokoll des Kontextmanagers zum Schließen des zugrunde liegenden Transports.

Ein funktionierendes Beispiel folgt. Der Servercode

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

Der Client-Code für den vorherigen Server

import xmlrpc.client

with xmlrpc.client.ServerProxy("https://:8000/") as proxy:
    print("3 is even: %s" % str(proxy.is_even(3)))
    print("100 is even: %s" % str(proxy.is_even(100)))

DateTime-Objekte

class xmlrpc.client.DateTime

Diese Klasse kann mit Sekunden seit der Epoche, einem Zeit-Tupel, einem ISO 8601 Zeit-/Datumsstring oder einer Instanz von datetime.datetime initialisiert werden. Sie hat die folgenden Methoden, die hauptsächlich für den internen Gebrauch durch den Marshalling-/Unmarshalling-Code unterstützt werden

decode(string)

Akzeptiert eine Zeichenkette als neuen Zeitwert der Instanz.

encode(out)

Schreibt die XML-RPC-Kodierung dieses DateTime-Elements in den Ausgabestrom out.

Es unterstützt auch bestimmte eingebaute Operatoren von Python durch Methoden wie reichhaltige Vergleiche und __repr__().

Ein funktionierendes Beispiel folgt. Der Servercode

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

Der Client-Code für den vorherigen Server

import xmlrpc.client
import datetime

proxy = xmlrpc.client.ServerProxy("https://: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"))

Binäre Objekte

class xmlrpc.client.Binary

Diese Klasse kann aus Byte-Daten (die auch NULs enthalten können) initialisiert werden. Der primäre Zugriff auf den Inhalt eines Binary-Objekts erfolgt über ein Attribut

data

Die von der Binary-Instanz umschlossenen Binärdaten. Die Daten werden als bytes-Objekt bereitgestellt.

Binary-Objekte haben die folgenden Methoden, die hauptsächlich für den internen Gebrauch durch den Marshalling-/Unmarshalling-Code unterstützt werden

decode(bytes)

Akzeptiert ein base64-kodiertes bytes-Objekt und dekodiert es als neue Daten der Instanz.

encode(out)

Schreibt die XML-RPC-Base64-Kodierung dieses binären Elements in den Ausgabestrom out.

Die kodierten Daten enthalten Zeilenumbrüche alle 76 Zeichen gemäß RFC 2045 Abschnitt 6.8, was der De-facto-Standard für Base64 war, als die XML-RPC-Spezifikation geschrieben wurde.

Es unterstützt auch bestimmte eingebaute Operatoren von Python durch die Methoden __eq__() und __ne__().

Beispiel für die Verwendung von Binärobjekten. Wir werden ein Bild über XMLRPC übertragen

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

Der Client erhält das Bild und speichert es in einer Datei

import xmlrpc.client

proxy = xmlrpc.client.ServerProxy("https://:8000/")
with open("fetched_python_logo.jpg", "wb") as handle:
    handle.write(proxy.python_logo().data)

Fault-Objekte

class xmlrpc.client.Fault

Ein Fault-Objekt kapselt den Inhalt eines XML-RPC-Fehlertags. Fault-Objekte haben die folgenden Attribute

faultCode

Eine Ganzzahl, die den Fehlertyp angibt.

faultString

Ein String, der eine Diagnosemeldung enthält, die mit dem Fehler verbunden ist.

Im folgenden Beispiel werden wir absichtlich einen Fault verursachen, indem wir ein komplexes Typobjekt zurückgeben. Der Servercode

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

Der Client-Code für den vorherigen Server

import xmlrpc.client

proxy = xmlrpc.client.ServerProxy("https://: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)

ProtocolError-Objekte

class xmlrpc.client.ProtocolError

Ein ProtocolError-Objekt beschreibt einen Protokollfehler in der zugrunde liegenden Transportschicht (wie z. B. ein 404 „nicht gefunden“-Fehler, wenn der durch die URI benannte Server nicht existiert). Es hat die folgenden Attribute

url

Die URI oder URL, die den Fehler ausgelöst hat.

errcode

Der Fehlercode.

errmsg

Die Fehlermeldung oder Diagnosezeichenkette.

headers

Ein Dictionary, das die Header der HTTP/HTTPS-Anfrage enthält, die den Fehler ausgelöst hat.

Im folgenden Beispiel werden wir absichtlich einen ProtocolError verursachen, indem wir eine ungültige URI bereitstellen

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)

MultiCall-Objekte

Das MultiCall-Objekt bietet eine Möglichkeit, mehrere Aufrufe an einen entfernten Server zu einer einzigen Anfrage zu kapseln [1].

class xmlrpc.client.MultiCall(server)

Erstellt ein Objekt, das zum Boxen von Methodenaufrufen verwendet wird. server ist das endgültige Ziel des Aufrufs. Aufrufe können an das Ergebnisobjekt gerichtet werden, aber sie geben sofort None zurück und speichern nur den Aufrufnamen und die Parameter im MultiCall-Objekt. Das Aufrufen des Objekts selbst bewirkt, dass alle gespeicherten Aufrufe als eine einzige system.multicall-Anfrage übertragen werden. Das Ergebnis dieses Aufrufs ist ein Generator; das Iterieren über diesen Generator liefert die einzelnen Ergebnisse.

Ein Anwendungsbeispiel dieser Klasse folgt. Der Servercode

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

Der Client-Code für den vorherigen Server

import xmlrpc.client

proxy = xmlrpc.client.ServerProxy("https://: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))

Komfortfunktionen

xmlrpc.client.dumps(params, methodname=None, methodresponse=None, encoding=None, allow_none=False)

Konvertiert params in eine XML-RPC-Anfrage oder in eine Antwort, wenn methodresponse wahr ist. params kann entweder ein Tupel von Argumenten oder eine Instanz der Klasse Fault sein. Wenn methodresponse wahr ist, kann nur ein einzelner Wert zurückgegeben werden, was bedeutet, dass params die Länge 1 haben muss. encoding, falls angegeben, ist die zu verwendende Kodierung im generierten XML; der Standard ist UTF-8. Pythons None-Wert kann in Standard-XML-RPC nicht verwendet werden; um ihn über eine Erweiterung verwenden zu können, geben Sie für allow_none einen wahren Wert an.

xmlrpc.client.loads(data, use_datetime=False, use_builtin_types=False)

Konvertiert eine XML-RPC-Anfrage oder -Antwort in Python-Objekte, ein (params, methodname). params ist ein Tupel von Argumenten; methodname ist ein String oder None, wenn kein Methodenname im Paket vorhanden ist. Wenn das XML-RPC-Paket einen Fehlerzustand darstellt, löst diese Funktion eine Ausnahme Fault aus. Das Flag use_builtin_types kann verwendet werden, um Datums-/Zeitwerte als datetime.datetime-Objekte und Binärdaten als bytes-Objekte darzustellen; dieses Flag ist standardmäßig falsch.

Das veraltete Flag use_datetime ist ähnlich wie use_builtin_types, aber es gilt nur für Datums-/Zeitwerte.

Geändert in Version 3.3: Das Flag use_builtin_types wurde hinzugefügt.

Beispiel für die Client-Nutzung

# simple test program (from the XML-RPC specification)
from xmlrpc.client import ServerProxy, Error

# server = ServerProxy("https://: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)

Um über einen HTTP-Proxy auf einen XML-RPC-Server zuzugreifen, müssen Sie einen benutzerdefinierten Transport definieren. Das folgende Beispiel zeigt, wie

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

Beispiel für Client- und Server-Nutzung

Siehe SimpleXMLRPCServer Beispiel.

Fußnoten