python - अजगर में SimpleXMLRPCServer के साथ** क्वार्ज का उपयोग करना




xmlrpclib (4)

XML-RPC में वास्तव में 'कीवर्ड तर्क' की कोई अवधारणा नहीं है, इसलिए xmlrpclib उन्हें समर्थन देने की कोशिश नहीं करता। आपको एक सम्मेलन लेने की आवश्यकता होगी, फिर कीवर्ड तर्कों को स्वीकार करने के लिए xmlrpclib.method को संशोधित करें और उस सम्मेलन के उपयोग के साथ उन्हें पास करें।

उदाहरण के लिए, मैं एक एक्सएमएल-आरपीसी सर्वर के साथ काम करता था जो दो तर्कों के रूप में कुंजीशब्द तर्क को पारित करता था, '-KEYWORD' वास्तविक तर्क के बाद, एक सपाट सूची में। मुझे उस कोड तक पहुंच नहीं है जो मैंने लिखा है कि XML-RPC सर्वर को पायथन से एक्सेस करने के लिए, लेकिन यह काफी सरल था:

import xmlrpclib

_orig_Method = xmlrpclib._Method

class KeywordArgMethod(_orig_Method):     
    def __call__(self, *args, **kwargs):
        if args and kwargs:
            raise TypeError, "Can't pass both positional and keyword args"
        args = list(args) 
        for key in kwargs:
            args.append('-%s' % key.upper())
            args.append(kwargs[key])
       return _orig_Method.__call__(self, *args)     

xmlrpclib._Method = KeywordArgMethod

यह बंदरपैचिंग का उपयोग करता है क्योंकि यह ऐसा करने के लिए सबसे आसान तरीका है, क्योंकि मॉड्यूल ग्लोबल्स और नाम-संदिग्ध विशेषताओं (उदाहरण के लिए, उदाहरण के लिए) ServerProxy क्लास के कुछ क्लंकी उपयोगों के कारण

मेरे पास एक ऐसा क्लास है जिसे मैं पीटाऑन्स सिम्प्लेक्सएक्सएलएलपीसीसरर का उपयोग कर एक दूरस्थ सेवा के रूप में बेनकाज़ करना चाहता हूं। सर्वर स्टार्टअप इस तरह दिखता है:

server = SimpleXMLRPCServer((serverSettings.LISTEN_IP,serverSettings.LISTEN_PORT))

service = Service()

server.register_instance(service)
server.serve_forever()

फिर मेरे पास एक ServiceRemote वर्ग है जो इस तरह दिखता है:

def __init__(self,ip,port):
    self.rpcClient = xmlrpclib.Server('http://%s:%d' %(ip,port))

def __getattr__(self, name):
    # forward all calls to the rpc client
    return getattr(self.rpcClient, name)

तो ServiceRemote ऑब्जेक्ट पर सभी कॉल xmlrpclib.Server के लिए अग्रेषित किए जाएंगे, जो उसके बाद उसे दूरस्थ सर्वर पर भेज देगा। समस्या उस सेवा में एक विधि है जिसे नामित varargs लिया गया है:

@useDb
def select(self, db, fields, **kwargs):
    pass

@useDb डेकोरेटर फ़ंक्शन को लपेटता है, कॉल करने से पहले डीबी बनाने और इसे खोलने के बाद, परिणाम को लौटने से पहले कॉल को पूरा करने के बाद इसे बंद कर दिया जाता है।

जब मैं इस विधि को कॉल करता हूं, तो मुझे त्रुटि मिलती है " कॉल () को एक अनपेक्षित कीवर्ड तर्क 'नाम' मिला है। तो, क्या संभवतः नामित चर नामित तर्कों को दूरस्थ रूप से कॉल करना संभव है? या मुझे प्रत्येक विधि भिन्नता की आवश्यकता के लिए ओवरराइड बनाना होगा।

प्रतिक्रियाओं के लिए धन्यवाद मैंने अपने कोड को थोड़ा बदल दिया है, इसलिए सवाल अब एक मुद्दा नहीं है। हालांकि अब मुझे भविष्य के संदर्भ के लिए यह पता है अगर मुझे वास्तव में स्थितीय तर्कों को लागू करना और रिमोट इनवॉन्स का समर्थन करना है। मुझे लगता है कि थॉमस और प्राप्ताप के दृष्टिकोण का संयोजन अच्छा होगा। क्लाइंट पर xmlrpclient के माध्यम से क्वार्विंग को स्थितीय आर्गिज़ में बदलना, और स्थितीय आर्ग्यूमेंट को खोलने के लिए तरीकों सर्वर पर एक आवरण होना।


आप इसे सादे xmlrpc के साथ नहीं कर सकते, क्योंकि इसके पास कीवर्ड तर्कों की कोई धारणा नहीं है। हालांकि, आप एक्सएमएलआरपीसी के शीर्ष पर एक प्रोटोकॉल के रूप में इसे अपरिवर्तित कर सकते हैं जो हमेशा पहली तर्क के रूप में एक सूची को पारित करता है, और एक शब्दकोश के रूप में एक शब्दकोश, और फिर उचित समर्थन कोड प्रदान करें ताकि यह आपके उपयोग के लिए पारदर्शी हो, नीचे दिए गए उदाहरण के लिए:

सर्वर

from SimpleXMLRPCServer import SimpleXMLRPCServer

class Server(object):
    def __init__(self, hostport):
        self.server = SimpleXMLRPCServer(hostport)

    def register_function(self, function, name=None):
        def _function(args, kwargs):
            return function(*args, **kwargs)
        _function.__name__ = function.__name__
        self.server.register_function(_function, name)

    def serve_forever(self):
        self.server.serve_forever()

#example usage
server = Server(('localhost', 8000))
def test(arg1, arg2):
    print 'arg1: %s arg2: %s' % (arg1, arg2)
    return 0
server.register_function(test)
server.serve_forever()

ग्राहक

import xmlrpclib

class ServerProxy(object):
    def __init__(self, url):
        self._xmlrpc_server_proxy = xmlrpclib.ServerProxy(url)
    def __getattr__(self, name):
        call_proxy = getattr(self._xmlrpc_server_proxy, name)
        def _call(*args, **kwargs):
            return call_proxy(args, kwargs)
        return _call

#example usage
server = ServerProxy('http://localhost:8000')
server.test(1, 2)
server.test(arg2=2, arg1=1)
server.test(1, arg2=2)
server.test(*[1,2])
server.test(**{'arg1':1, 'arg2':2})

जहाँ तक मुझे पता है, अंतर्निहित प्रोटोकॉल नामित varargs (या उस बात के लिए किसी भी नाम दिया args) का समर्थन नहीं करता है। इसके लिए समाधान एक आवरण बनाने के लिए है, जो कि ** क्वार्ज ले जाएगा और इसे आप जिस पद्धति को कॉल करना चाहते हैं उसे साधारण शब्दकोष के रूप में देना होगा। कुछ इस तरह

सर्वर साइड:

def select_wrapper(self, db, fields, kwargs):
    """accepts an ordinary dict which can pass through xmlrpc"""
    return select(self,db,fields, **kwargs)

क्लाइंट साइड पर:

def select(self, db, fields, **kwargs):
    """you can call it with keyword arguments and they will be packed into a dict"""
    return self.rpcClient.select_wrapper(self,db,fields,kwargs)

अस्वीकरण: कोड सामान्य विचार दिखाता है, आप इसे थोड़ा क्लीनर कर सकते हैं (उदाहरण के लिए एक डेकोरेटर लिखकर ऐसा करने के लिए)।


थॉमस वाउटर ने कहा था कि एक्सएमएल-आरपीसी में खोजशब्द तर्क नहीं है। जहां तक ​​प्रोटोकॉल का संबंध है, केवल तर्कों का क्रम मानता है और उन्हें XML में कुछ भी कहा जा सकता है: arg0, arg1, arg2 बिल्कुल ठीक है, जैसा कि एक ही तर्क के लिए पनीर, कैंडी और बेकन है।

शायद आपको बस प्रोटोकॉल के आपके उपयोग को पुनर्विचार करना चाहिए? दस्तावेज़ / शाब्दिक SOAP जैसे कुछ का उपयोग करना एक वैकल्पिक हल से बेहतर होगा जैसे कि अन्य उत्तरों में प्रस्तुत किए गए हैं। बेशक, यह संभव नहीं हो सकता है।





xmlrpclib