GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||
GeezerVison is showing python.github.io — xmlrpc.client --- دسترسی کلاینت XML-RPC
|
نوع XML-RPC |
نوع پایتون |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ثابت |
|
|
این مجموعهی کاملی از انواع داده است که توسط XML-RPC پشتیبانی میشود. فراخوانیهای متد همچنین ممکن است یک نمونهی خاص از Fault را پرتاب کنند که برای نشان دادن خطاهای سرور XML-RPC استفاده میشود، یا ProtocolError که برای نشان دادن خطایی در لایهی انتقال HTTP/HTTPS استفاده میشود. هر دو Fault و ProtocolError از یک کلاس پایه به نام Error مشتق شدهاند. توجه داشته باشید که ماژول کلاینتی xmlrpc در حال حاضر نمونههای زیرکلاسهای انواع توکار را مارشال (marshal) نمیکند.
هنگام ارسال رشتهها، نویسههای ویژهی XML مانند <، > و & بهطور خودکار خنثی میشوند. با این حال، بر عهدهی فراخواننده است که اطمینان حاصل کند رشته عاری از نویسههایی است که در XML مجاز نیستند، مانند نویسههای کنترلی با مقادیر ASCII بین ۰ تا ۳۱ (البته بهجز تب، خط جدید و بازگشت به ابتدای سطر)؛ عدم انجام این کار باعث میشود درخواست XML-RPC حاصل، XML خوشساخت نباشد. اگر نیاز به ارسال بایتهای دلخواه از طریق XML-RPC دارید، از کلاسهای bytes یا bytearray یا کلاس پوششی Binary که در ادامه توضیح داده شده است استفاده کنید.
Server برای سازگاری با نسخههای قبلی، بهعنوان نام مستعاری برای ServerProxy نگه داشته شده است. کدهای جدید باید از ServerProxy استفاده کنند.
تغییر یافته در نسخهی 3.5: آرگومان context اضافه شد.
تغییر یافته در نسخهی 3.6: پشتیبانی از برچسبهای نوع دارای پیشوند (برای مثال ex:nil) افزوده شد. پشتیبانی از بازگشایی (unmarshalling) انواع اضافی که پیادهسازی Apache XML-RPC برای مقادیر عددی استفاده میکند، افزوده شد: i1، i2، i8، biginteger، float و bigdecimal. برای توضیحات، https://ws.apache.org/xmlrpc/types.html را ببینید.
همچنین ببینید
توضیحی خوب دربارهی عملکرد XML-RPC و نرمافزارهای کلاینت به چند زبان. تقریباً شامل همهی چیزهایی است که یک توسعهدهندهی کلاینت XML-RPC باید بداند.
افزونهی پروتکل XML-RPC برای دروننگری را توصیف میکند.
مشخصات رسمی.
یک نمونه از ServerProxy دارای متدی متناظر با هر فراخوانی روش راه دور (RPC) پذیرفتهشده توسط سرور XML-RPC است. فراخوانی این متد یک RPC را اجرا میکند که هم بر اساس نام و هم بر اساس امضای آرگومانها دیسپچ میشود (مثلاً یک نام متد واحد را میتوان با چند امضای آرگومان سربارگذاریکرد). اجرای RPC یا با بازگرداندن داده در یک نوع سازگار و یا با بالا آوردن یک استثنای Fault یا ProtocolError که نشاندهندهی یک خطا است، به پایان میرسد.
سرورهایی که از API دروننگری XML پشتیبانی میکنند، از برخی متدهای رایج پشتیبانی میکنند که زیر ویژگی محفوظ system گروهبندی شدهاند:
این متد فهرستی از رشتهها را برمیگرداند، یکی برای هر متد (غیرسیستمی) که توسط سرور XML-RPC پشتیبانی میشود.
این متد یک پارامتر میگیرد، نام متدی که توسط سرور XML-RPC پیادهسازیشده است. این متد آرایهای از امضاهای ممکن برای این متد برمیگرداند. یک امضا آرایهای از نوعها است. اولین مورد از این نوعها، نوع بازگشتی متد است و بقیه، پارامترها هستند.
از آنجا که چندین امضا، یعنی سربارگذاری (overloading)، مجاز است، این متد بهجای تکنمونه، فهرستی از امضاها را برمیگرداند.
خود امضاها به پارامترهای سطح بالایی که یک متد انتظار دارد محدود میشوند. برای مثال، اگر متدی یک آرایه از ساختارها را بهعنوان پارامتر انتظار داشته باشد و یک رشته را برگرداند، امضای آن بهسادگی "string, array" است. اگر سه عدد صحیح را انتظار داشته باشد و یک رشته را برگرداند، امضای آن "string, int, int, int" است.
اگر هیچ امضایی برای متد تعریف نشده باشد، یک مقدار غیرآرایهای برگردانده میشود. در پایتون، این بدان معنا است که نوع مقدار برگرداندهشده چیزی غیر از فهرست خواهد بود.
این متد یک پارامتر میگیرد، نام متدی که توسط سرور XML-RPC پیادهسازی شده است. این متد یک رشته مستندسازی برمیگرداند که کاربرد آن متد را توصیف میکند. اگر چنین رشتهای در دسترس نباشد، یک رشته خالی برگردانده میشود. رشته مستندسازی ممکن است حاوی نمادگذاری HTML باشد.
تغییر یافته در نسخهی 3.5: نمونههای ServerProxy از پروتکل context manager برای بستن انتقال زیرین پشتیبانی میکنند.
در ادامه یک مثال کاربردی آمده است. کد سرور:
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)))
این کلاس را میتوان با ثانیههای سپریشده از مبدأ زمانی، یک تاپل زمانی، یک رشته زمان/تاریخ ISO 8601، یا یک نمونه datetime.datetime مقداردهی اولیه کرد. این کلاس متدهای زیر را دارد که عمدتاً برای استفاده داخلی توسط کد مارشالینگ/مارشالگشایی پشتیبانی میشوند:
یک رشته را بهعنوان مقدار زمانی جدید نمونه میپذیرد.
همچنین از برخی از عملگرهای توکار پایتون از طریق متدهای مقایسه غنی و __repr__() پشتیبانی میکند.
در ادامه یک مثال کاربردی آمده است. کد سرور:
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() # convert the ISO 8601 string to a datetime object converted = dt.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S") print(f"Today: {converted.strftime('%d.%m.%Y, %H:%M')}")
این کلاس میتواند از دادههای بایتی (که ممکن است شامل نویسههای NUL باشد) مقداردهی اولیه شود. دسترسی اصلی به محتوای یک شیء Binary از طریق یک ویژگی فراهم میشود:
دادههای دودویی کپسولهشده توسط نمونهی Binary. این دادهها بهصورت یک شیء bytes ارائه میشوند.
اشیای Binary متدهای زیر را دارند، که عمدتاً برای استفادهی داخلی توسط کد مارشالینگ/مارشالگشایی (marshalling/unmarshalling) پشتیبانی میشوند:
یک شیء bytes با کدگذاری base64 را میپذیرد و آن را بهعنوان دادهی جدید نمونه کدگشایی میکند.
کدگذاری base 64 مربوط به XML-RPC برای این آیتم دودویی را در شیء جریان out بنویسید.
دادههای کدگذاریشده مطابق RFC 2045 section 6.8، که در زمان نگارش مشخصات XML-RPC مشخصات استاندارد دوفاکتو (de facto) برای base64 بود، هر ۷۶ نویسه یک خط جدید خواهند داشت.
همچنین از برخی از عملگرهای توکار پایتون از طریق متدهای __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)
یک شیء Fault محتوای برچسب fault در XML-RPC را در بر میگیرد. اشیای Fault دارای ویژگیهای زیر هستند:
یک عدد صحیح که نوع خطا را نشان میدهد.
رشتهای حاوی پیام تشخیصی مرتبط با خطا.
در مثال زیر، عمداً با برگرداندن یک شیء با نوع پیچیده، باعث ایجاد 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)
یک شیء ProtocolError یک خطای پروتکل در لایهی انتقال زیرین را توصیف میکند (مانند خطای ۴۰۴ «یافت نشد» در صورتی که سرور مشخصشده با URI وجود نداشته باشد). این شیء دارای ویژگیهای زیر است:
URI یا URLی که باعث ایجاد خطا شد.
کد خطا.
پیام خطا یا رشتهی تشخیصی.
یک دیکشنری شامل سرآیندهای درخواست HTTP/HTTPS که باعث ایجاد خطا شده است.
در مثال زیر، قصد داریم عمداً با ارائه یک URI نامعتبر، یک ProtocolError ایجاد کنیم:
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 راهی برای کپسولهکردن چندین فراخوانی به یک سرور دوردست در قالب یک درخواست فراهم میکند [1].
یک شیء برای جعبهگذاری (boxcar) فراخوانیهای متد ایجاد کنید. 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))
params را به یک درخواست XML-RPC، یا در صورتی که methodresponse true باشد، به یک پاسخ تبدیل میکند. params میتواند یک تاپل از آرگومانها یا نمونهای از کلاس استثنای Fault باشد. اگر methodresponse true باشد، تنها یک مقدار میتواند برگردانده شود، به این معنا که params باید طول ۱ داشته باشد. encoding، در صورت ارائه، کدگذاری مورد استفاده در XML تولیدشده است؛ پیشفرض UTF-8 است. مقدار None پایتون نمیتواند در XML-RPC استاندارد استفاده شود؛ برای مجاز کردن استفاده از آن از طریق یک افزونه، یک مقدار true برای allow_none ارائه دهید.
یک درخواست یا پاسخ XML-RPC را به اشیای پایتون تبدیل میکند: یک (params, methodname). params یک تاپل از آرگومانها است؛ methodname یک رشته است، یا اگر نام متدی در بسته وجود نداشته باشد None است. اگر بستهی XML-RPC نشاندهندهی یک وضعیت خطا باشد، این تابع استثنای Fault را پرتاب میکند. میتوان از پرچم use_builtin_types استفاده کرد تا مقادیر تاریخ/زمان بهصورت اشیای datetime.datetime و دادههای دودویی بهصورت اشیای bytes ارائه شوند؛ این پرچم بهطور پیشفرض نادرست است.
پرچم منسوخ use_datetime مشابه use_builtin_types است، اما فقط به مقادیر تاریخ/زمان اعمال میشود.
تغییر یافته در نسخهی 3.3: پرچم use_builtin_types افزوده شد.
# 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))
مثال SimpleXMLRPCServer را ببینید.
پانویسها