Python example code for passing objects in xml-rpc

1. XML document

  • XML
  • C parsing library for libxml2 XML

2. Explanation

  • When using docopt, please note that
    • The command description format for docopt is xxx
    • New command for docopt, do_Heading
  • When using class, attention should be paid to
    • Class function, the first parameter cls cannot be missing

3. Client Example Code

import xmlrpc.client
import sys
import json
import cmd
import urllib
from docopt import docopt, DocoptExit
from colorama import init, Fore
import time

class ServerInfo(object):
"""used to define server-side information"""

ServerIP = ''
ServerPort = ''

@classmethod
def LoadServerInfo(cls):
  cls.ServerIP = '127.0.0.1'
  cls.ServerPort = '5000'

@classmethod
def GetServerAddr(cls):
  """used to obtain server address"""
  return (cls.ServerIP, cls.ServerPort)

@classmethod
def GetServerUrl(cls):
  if (cls.ServerIP == '') or (cls.ServerPort == ''):
      return ''
  return  xmlrpc.client.ServerProxy('http://' + cls.ServerIP
              + ':' + cls.ServerPort
              )


#define a decoration function to parse the command line 
def docopt_cmd(func):
"""
This decorator is used to simplify the try/except block and pass the result
of the docopt parsing to the called action.
"""
def fn(self, arg):
  try:
      opt = docopt(fn.__doc__, arg)

  except DocoptExit as e:
      # The DocoptExit is thrown when the args do not match.
      # We print a message to the user and the usage block.

      print('Invalid Command!')
      print(e)
      return

  except SystemExit:
      # The SystemExit exception prints the usage for --help
      # We do not need to do the print here.
      return

  return func(self, opt)

fn.__name__= func.__name__
fn.__doc__= func.__doc__
fn.__dict__.update(func.__dict__)
return fn


class MyInteractive (cmd.Cmd):
"""this class is used to provide a command-line interface and interact with the server"""

# intro it's the welcome interface 
intro = """***********************************
======Welcome to csdn ftz server-client!=======
(type help for a list of commands.)
***********************************"""

# prompt it's a prompt 
prompt = 'ftz_csdn> '

@docopt_cmd
def do_plusCaculate(self, arg):
  """Usage:
  plusCaculate --a=<int> --b=<int>
  Options:
      --a=<int>  para 1
      --b=<int>  para 2
  """
  s = ServerInfo().GetServerUrl()
  a = int(arg['--a'])
  b = int(arg['--b'])
  print(s.aPLusb(a,b))

@docopt_cmd
def do_minusCaculate(self, arg):
  """Usage:
  minusCaculate --a=<int> --b=<int>
  Options:
      --a=<int>  para 1
      --b=<int>  para 2
  """
  s = ServerInfo().GetServerUrl()
  a = int(arg['--a'])
  b = int(arg['--b'])
  print(s.aMinusb(a,b))

@docopt_cmd
def do_add_user(self, arg):
  """Usage:
  add_user --id=<string> --name=<string> --age=<int> --city=<string>
  Options:
      --id=<string>  para 1
      --name=<string>  para 2
      --age=<int>  para 3 
      --city=<string>  para 4 
  """
  s = ServerInfo().GetServerUrl()
  i = arg['--id']
  name = arg['--name']
  age = int(arg['--age'])
  city = arg['--city']
  user = dict()
  user["name"]=name
  user["age"]=age
  user["city"]=city
  print(s.add_user(i, user))
@docopt_cmd
def do_get_user(self, arg):
  """Usage:
  get_user --id=<string>
  Options:
      --id=<string>  para 1
  """
  s = ServerInfo().GetServerUrl()
  i = arg['--id']
  print(s.get_user(i))
@docopt_cmd
def do_show_user(self, arg):
  """Usage:
  show_user
  """
  s = ServerInfo().GetServerUrl()
  print(s.show_user())
@docopt_cmd
def do_update_user(self, arg):
  """Usage:
  update_user --id=<string> --name=<string> --age=<int> --city=<string>
  Options:
      --id=<string>  para 1
      --name=<string>  para 2
      --age=<int>  para 3 
      --city=<string>  para 4 
  """
  s = ServerInfo().GetServerUrl()
  i = arg['--id']
  name = arg['--name']
  age = int(arg['--age'])
  city = arg['--city']
  user = dict()
  user["name"]=name
  user["age"]=age
  user["city"]=city
  print(s.update_user(i, user))
@docopt_cmd
def do_del_user(self, arg):
  """Usage:
  del_user --id=<string> 
  Options:
      --id=<string>  para 1
  """
  s = ServerInfo().GetServerUrl()
  i = arg['--id']
  print(s.del_user(i))
def do_quit(self, arg):
	"""Quits out of Interactive Mode."""
	sys.exit()
def emptyline(self):
  print('ftz_csdn> ')

if __name__== '__main__':
	#init(autoreset=True)
	ServerInfo().LoadServerInfo()
	MyInteractive().cmdloop()

4. Server Example Code

# -*- coding: utf-8 -*-
import json
import os
from urllib import request
import urllib
from socketserver import ThreadingMixIn
from xmlrpc.server import SimpleXMLRPCServer
from xmlrpc.server import SimpleXMLRPCRequestHandler

class Processor(object):
d=dict()
@classmethod
def aPLusb(cls,a,b):
  return a+b
@classmethod
def aMinusb(cls,a,b):
  return a-b

@classmethod
def add_user(cls, key, value):
  cls.d[key]=value
  #print(cls.d)
  return key
@classmethod
def get_user(cls, key):
  if key in cls.d.keys():
      #print(key)
      return cls.d[key]
  else:
      #print(key)
      #print(type(key))
      return None
@classmethod
def update_user(cls, key, value):
  cls.d[key]=value
  return key
@classmethod
def del_user(cls, key):
  if key in cls.d.keys():
      cls.d.pop(key)
  #else:
  #    print(type(key), key)
  
  return key
@classmethod
def show_user(cls):
  return cls.d

class Listener(object):
"""used to describe a listening server"""
ListenerIP = ''
ListenerPort = ''
Server = ''

#read ip and port
@classmethod
def LoadListener(cls):
  cls.ListenerIP = '127.0.0.1'
  cls.ListenerPort = 5000 
  print('ListenerAddr: ' + cls.ListenerIP + ':' +  str(cls.ListenerPort))

  #designated access RPC server's URL prefix 
  class RequestHandler(SimpleXMLRPCRequestHandler): rpc_paths = ('/RPC2',)

  #create server 
  class MyXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
      daemon_threads =True

  cls.Server = MyXMLRPCServer((cls.ListenerIP, cls.ListenerPort),
   requestHandler=RequestHandler, allow_none=True)

  #support listing all methods supported by the server 
  cls.Server.register_introspection_functions()

#register RPC function 
@classmethod
def RegisterFunction(cls, Func, FuncDesc):
  cls.Server.register_function(Func, FuncDesc)

#start-up XMLRPC server 
@classmethod
def StartListener(cls):
  cls.Server.serve_forever()

if __name__== '__main__':
#register RPC function 
Listener = Listener()
Listener.LoadListener()
Processor = Processor()

#registering computing services 
Listener.RegisterFunction(Processor.aPLusb, 'aPLusb')
Listener.RegisterFunction(Processor.aMinusb, 'aMinusb')

#registration object service 
Listener.RegisterFunction(Processor.add_user, 'add_user')
Listener.RegisterFunction(Processor.get_user, 'get_user')
Listener.RegisterFunction(Processor.update_user, 'update_user')
#Listener.RegisterFunction(Processor.del_user, 'del_user')
Listener.RegisterFunction(Processor.show_user, 'show_user')

#start listening 
Listener.StartListener()

Related articles