xmlrpc.client --- XML-RPC クライアントアクセス¶
ソースコード: Lib/xmlrpc/client.py
XML-RPCはXMLを利用した遠隔手続き呼び出し(Remote Procedure Call)の一種で、HTTP(S)をトランスポートとして使用します。XML- RPCでは、クライアントはリモートサーバ(URIで指定されたサーバ)上のメソッドをパラメータを指定して呼び出し、構造化されたデータを取得します。このモジュールは、XML-RPCクライアントの開発をサポートしており、Pythonオブジェクトに適合する転送用XMLの変換の全てを行います。
警告
xmlrpc.client モジュールは、悪意を持って作成されたデータに対して安全ではありません。
信頼できないデータや認証されていないデータを解析する必要がある場合は、XML のセキュリティ を参照してください。
バージョン 3.5 で変更: HTTPS URI に対して、xmlrpc.client は必要な証明書とホスト名の検証をデフォルトですべて行うようになりました。
利用可能な環境: not WASI.
このモジュールは WebAssembly では動作しないか、利用不可です。詳しくは、WebAssembly プラットフォーム を見てください。
- class xmlrpc.client.ServerProxy(uri, transport=None, encoding=None, verbose=False, allow_none=False, use_datetime=False, use_builtin_types=False, *, headers=(), context=None)¶
ServerProxyは、リモートのXML-RPCサーバとの通信を管理するオブジェクトです。最初のパラメータはURI(Uniform Resource Indicator)で、通常はサーバのURLを指定します。2番目のパラメータにはトランスポート・ファクトリを指定する事ができます。トランスポート・ファクトリを省略した場合、URLが https: ならモジュール内部のSafeTransportインスタンスを使用し、それ以外の場合にはモジュール内部のTransportインスタンスを使用します。オプションの 3 番目の引数はエンコード方法で、デフォルトでは UTF-8 です。オプションの 4 番目の引数はデバッグフラグです。以下の引数は、返されるプロキシインスタンスの動作を制御します。 allow_none が真の場合、Python の定数
Noneは XML に変換されます。 デフォルトではNoneを渡すとTypeErrorが送出されます。 これは XML-RPC 仕様のよく使われる拡張ですが、すべてのクライアントやサーバーがサポートしているわけではありません。 説明は http://ontosys.com/xml-rpc/extensions.php を参照してください。 use_builtin_types フラグを使うと、日時の値をdatetime.datetimeオブジェクト、バイナリデータをbytesオブジェクトとして受け取れます。 このフラグのデフォルトは偽です。 呼び出しにはdatetime.datetime、bytes、bytearrayオブジェクトを渡せます。 headers は各リクエストで送信する HTTP ヘッダーを指定する省略可能な引数で、ヘッダー名と値を表す 2 要素のタプルのシーケンス (例えば[('Header-Name', 'value')]) で指定します。 HTTPS URL を指定した場合、context にssl.SSLContextを指定して、内部の HTTPS 接続の SSL 設定を構成できます。 旧式の use_datetime フラグは use_builtin_types と似ていますが、日時の値にだけ適用されます。バージョン 3.3 で変更: use_builtin_types フラグが追加されました。
バージョン 3.8 で変更: headers 引数が追加されました。
HTTP及びHTTPS通信の両方で、
http://user:pass@host:port/pathのようなHTTP基本認証のための拡張URL構文をサポートしています。user:passはbase64でエンコードしてHTTPの'Authorization 'ヘッダとなり、XML-RPCメソッド呼び出し時に接続処理の一部としてリモートサーバに送信されます。リモートサーバが基本認証を要求する場合のみ、この機能を利用する必要があります。生成されるインスタンスはリモートサーバへのプロクシオブジェクトで、RPC呼び出しを行う為のメソッドを持ちます。リモートサーバがイントロスペクション APIをサポートしている場合は、リモートサーバのサポートするメソッドを検索 (サービス検索)やサーバのメタデータの取得なども行えます。
以下の型をXMLに変換(XMLを通じてマーシャルする)する事ができます (特別な指定がない限り、逆変換でも同じ型として変換されます):
XML-RPC の型
Python の型
booleanint,i1,i2,i4,i8またはbiginteger-2147483648 から 2147483647 までの範囲の
int。 値には<int>タグが付けられます。doubleまたはfloatfloat。 値には<double>タグが付けられます。stringarraystructdict。 キーは文字列でなければならず、値には変換可能な任意の型を使用できます。 ユーザー定義クラスのインスタンスも渡せますが、転送されるのは__dict__属性だけです。dateTime.iso8601DateTimeまたはdatetime.datetime。返される型は use_builtin_types および use_datetime の値に依ります。base64Binary、bytesまたはbytearray。返される型は use_builtin_types フラグの値に依ります。nilNone定数。 allow_none が真の場合にのみ渡すことが出来ます。bigdecimaldecimal.Decimal。 返される値としてのみ使われます。以上が XML-RPC でサポートされるデータ型のすべてです。 メソッド呼び出しでは、XML-RPC サーバーのエラーを表す
Faultインスタンスや、HTTP/HTTPS トランスポート層のエラーを表すProtocolErrorが送出されることもあります。FaultとProtocolErrorは、どちらもErrorという基底クラスから派生しています。 現在の xmlrpc クライアントモジュールは、組み込み型のサブクラスのインスタンスをマーシャルできないことに注意してください。文字列を渡す場合、
<,>,&などのXMLで特殊な意味を持つ文字は自動的にエスケープされます。しかし、ASCII値0〜31の制御文字(もちろん、タブ'TAB',改行'LF',リターン'CR'は除く)などのXMLで使用することのできない文字を使用することはできず、使用するとそのXML-RPCリクエストはwell-formedなXMLとはなりません。そのようなバイト列を渡す必要がある場合は、bytes,bytearrayクラスまたは後述のBinaryラッパークラスを使用してください。Serverは、後方互換性の為にServerProxyの別名として残されています。新しいコードではServerProxyを使用してください。バージョン 3.5 で変更: context 引数が追加されました。
バージョン 3.6 で変更: 接頭辞付きの型タグ (
ex:nilなど) をサポートしました。 Apache の XML-RPC 実装が数値に使う追加の型i1、i2、i8、biginteger、float、bigdecimalのアンマーシャルをサポートしました。 説明は https://ws.apache.org/xmlrpc/types.html を参照してください。
参考
- XML-RPC HOWTO
数種類のプログラミング言語で記述された XML-RPCの操作とクライアントソフトウェアの素晴らしい説明が掲載されています。 XML- RPCクライアントの開発者が知っておくべきことがほとんど全て記載されています。
- XML-RPC Introspection
インストロペクションをサポートする、 XML-RPC プロトコルの拡張を解説しています。
- XML-RPC Specification
公式の仕様
ServerProxy オブジェクト¶
ServerProxy インスタンスには、XML-RPC サーバーが受け付ける各リモート手続き呼び出しに対応するメソッドがあります。
メソッドを呼び出すと、名前と引数のシグネチャの両方に基づいて RPC が実行されます (例えば、同じメソッド名に対して引数のシグネチャが異なる複数の処理をオーバーロードできます)。
RPC は対応する型のデータを返すか、エラーを示す Fault または ProtocolError 例外を送出して終了します。
XML イントロスペクション API をサポートするサーバーは、予約された system 属性の下にまとめられた共通のメソッドを提供します。
- ServerProxy.system.listMethods()¶
XML-RPCサーバがサポートするメソッド名(system以外)を格納する文字列のリストを返します。
- ServerProxy.system.methodSignature(name)¶
XML-RPCサーバで実装されているメソッドの名前を指定し、利用可能なシグネチャの配列を取得します。シグネチャは型のリストで、先頭の型は戻り値の型を示し、以降はパラメータの型を示します。
XML-RPCでは複数のシグネチャ(オーバロード)を使用することができるので、単独のシグネチャではなく、シグネチャのリストを返します。
シグネチャは、メソッドが使用する最上位のパラメータにのみ適用されます。例えばあるメソッドのパラメータが構造体の配列で戻り値が文字列の場合、シグネチャは単に"string, array" となります。パラメータが三つの整数で戻り値が文字列の場合は"string, int, int, int"となります。
メソッドにシグネチャが定義されていない場合、配列以外の値が返ります。 Pythonでは、この値はlist以外の値となります。
- ServerProxy.system.methodHelp(name)¶
XML-RPC サーバーが実装するメソッドの名前を引数として 1 つ受け取り、そのメソッドの使い方を説明する文書文字列を返します。 そのような文字列がない場合は空文字列を返します。 文書文字列には 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)))
DateTime オブジェクト¶
- class xmlrpc.client.DateTime¶
このクラスは、エポックからの秒数、タプルで表現された時刻、ISO 8601形式の時間/日付文字列、
datetime.datetimeのインスタンスのいずれかで初期化することができます。 このクラスには以下のメソッドがあり、主にマーシャル/アンマーシャルを行うコードから内部的に使用されます:- decode(string)¶
文字列をインスタンスの新しい時間を示す値として指定します。
拡張比較メソッドと__repr__()メソッドを通じて、Python の組み込み演算子の一部もサポートしています。
以下は、動作する例です。サーバ側のコード:
import datetime as dt
from xmlrpc.server import SimpleXMLRPCServer
import xmlrpc.client
def today():
today = dt.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 as dt
proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
today = proxy.today()
# ISO 8601 形式の文字列を datetime オブジェクトに変換する
converted = dt.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S")
print(f"Today: {converted.strftime('%d.%m.%Y, %H:%M')}")
Binary オブジェクト¶
- class xmlrpc.client.Binary¶
このクラスは、バイト列データ(NULを含む)で初期化することができます。
Binaryの内容は、属性で参照します:Binaryオブジェクトは以下のメソッドを持ち、主に内部的にマーシャル/アンマーシャル時に使用されます:- encode(out)¶
バイナリ値をbase64でエンコードし、出力ストリームオブジェクト out に出力します。
エンコードされたデータは、 RFC 2045 section 6.8 にある通り、76文字ごとに改行されます。これは、XMC-RPC仕様が作成された時のデ・ファクト・スタンダードのbase64です。
__eq__()メソッドと__ne__()メソッドを通じて、Python の組み込み演算子の一部もサポートしています。
バイナリオブジェクトの使用例です。 XML-RPCごしに画像を転送します。
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)
Fault オブジェクト¶
- class xmlrpc.client.Fault¶
Faultオブジェクトは、XML-RPCのfaultタグの内容をカプセル化しており、以下の属性を持ちます:- faultCode¶
失敗のタイプを示す整数。
- faultString¶
失敗の診断メッセージを含む文字列。
以下のサンプルでは、複素数型のオブジェクトを返そうとして、故意に Fault を起こしています。
from xmlrpc.server import SimpleXMLRPCServer
# 複素数を返すため、マーシャル時にエラーが発生する
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)
ProtocolError オブジェクト¶
- class xmlrpc.client.ProtocolError¶
ProtocolErrorオブジェクトはトランスポート層で発生したエラー(URI で指定したサーバが見つからなかった場合に発生する404 'not found'など)の内容を示し、以下の属性を持ちます:- url¶
エラーの原因となったURIまたはURL。
- errcode¶
エラーコード。
- errmsg¶
エラーメッセージまたは診断文字列。
- headers¶
エラーの原因となった HTTP/HTTPS リクエストのヘッダーを含む辞書。
次の例では、不適切な URI を利用して、故意に ProtocolError を発生させています:
import xmlrpc.client
# XMLRPC リクエストに応答しない URI で ServerProxy を作成する
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 オブジェクト¶
MultiCall オブジェクトは遠隔のサーバに対する複数の呼び出しをひとつのリクエストにカプセル化する方法を提供します [1]。
- class xmlrpc.client.MultiCall(server)¶
Create 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 arguments in theMultiCallobject. Calling the object itself causes all stored calls to be transmitted as a singlesystem.multicallrequest. The result of this call is a generator; iterating over this generator yields the individual results.
以下は、このクラスの使用例です。サーバ側のコード:
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
# 簡単な算術関数を持つシンプルなサーバー
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))
補助関数¶
- xmlrpc.client.dumps(params, methodname=None, methodresponse=None, encoding=None, allow_none=False)¶
Convert params into an XML-RPC request, or into a response if methodresponse is true. params can be either a tuple of arguments or an instance of the
Faultexception class. If methodresponse is true, only a single value can be returned, meaning that params must be of length 1. encoding, if supplied, is the encoding to use in the generated XML; the default is UTF-8. Python'sNonevalue cannot be used in standard XML-RPC; to allow using it via an extension, provide a true value for allow_none.
- xmlrpc.client.loads(data, use_datetime=False, use_builtin_types=False)¶
XML-RPC リクエストまたはレスポンスを
(params, methodname)の形式をとる Python オブジェクトにします。 params は引数のタプルです。 methodname は文字列で、パケット中にメソッド名がない場合にはNoneになります。例外条件を示す XML-RPC パケットの場合には、Fault例外を送出します。 use_builtin_types フラグはdatetime.datetimeのオブジェクトとして日付/時刻を、bytesのオブジェクトとしてバイナリデータを表現する時に使用し、デフォルトでは false に設定されています。非推奨となった use_datetime フラグは use_builtin_types に似ていますが date/time 値にのみ適用されます。
バージョン 3.3 で変更: use_builtin_types フラグが追加されました。
クライアントのサンプル¶
# 簡単なテストプログラム (XML-RPC 仕様から引用)
from xmlrpc.client import ServerProxy, Error
# server = ServerProxy("http://localhost:8000") # ローカルサーバー
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))
クライアントとサーバーの利用例¶
SimpleXMLRPCServer の例 を参照してください。
脚注