xmlrpc.server.SimpleXMLRPCServer

原文地址:https://pymotw.com/2/SimpleXMLRPCServer/SimpleXMLRPCServer – Implements an XML-RPC server.
Purpose:    Implements an XML-RPC server.
Available In:    2.2 and later
The SimpleXMLRPCServer module contains classes for creating your own cross-platform, language-independent server using the XML-RPC protocol. Client libraries exist for many other languages, making XML-RPC an easy choice for building RPC-style services.

Note All of the examples provided here include a client module as well to interact with the demonstration server. If you want to download the code and run the examples, you will want to use 2 separate shell windows, one for the server and one for the client.
A Simple Server

This simple server example exposes a single function that takes the name of a directory and returns the contents. The first step is to create the SimpleXMLRPCServer instance and tell it where to listen for incoming requests (‘localhost’ port 9000 in this case). Then we define a function to be part of the service, and register the function so the server knows how to call it. The final step is to put the server into an infinite loop receiving and responding to requests.

from SimpleXMLRPCServer import SimpleXMLRPCServer
import logging
import os

# Set up logging
logging.basicConfig(level=logging.DEBUG)

server = SimpleXMLRPCServer((‘localhost‘, 9000), logRequests=True)

# Expose a function
def list_contents(dir_name):
    logging.debug(‘list_contents(%s)‘, dir_name)
    return os.listdir(dir_name)
server.register_function(list_contents)

try:
    print ‘Use Control-C to exit‘
    server.serve_forever()
except KeyboardInterrupt:
    print ‘Exiting‘
The server can be accessed at the URL http://localhost:9000 using xmlrpclib. This client code illustrates how to call the list_contents() service from Python.

import xmlrpclib

proxy = xmlrpclib.ServerProxy(‘http://localhost:9000‘)
print proxy.list_contents(‘/tmp‘)
Notice that we simply connect the ServerProxy to the server using its base URL, and then call methods directly on the proxy. Each method invoked on the proxy is translated into a request to the server. The arguments are formatted using XML, and then POSTed to the server. The server unpacks the XML and figures out what function to call based on the method name invoked from the client. The arguments are passed to the function, and the return value is translated back to XML to be returned to the client.

Starting the server gives:

$ python SimpleXMLRPCServer_function.py
Use Control-C to exit
Running the client in a second window shows the contents of my /tmp directory:

$ python SimpleXMLRPCServer_function_client.py
[‘.s.PGSQL.5432‘, ‘.s.PGSQL.5432.lock‘, ‘.X0-lock‘, ‘.X11-unix‘, ‘ccc_exclude.1mkahl‘,
‘ccc_exclude.BKG3gb‘, ‘ccc_exclude.M5jrgo‘, ‘ccc_exclude.SPecwL‘, ‘com.hp.launchport‘, ‘emacs527‘,
‘hsperfdata_dhellmann‘, ‘launch-8hGHUp‘, ‘launch-RQnlcc‘, ‘launch-trsdly‘, ‘launchd-242.T5UzTy‘,
‘var_backups‘]
and after the request is finished, log output appears in the server window:

$ python SimpleXMLRPCServer_function.py
Use Control-C to exit
DEBUG:root:list_contents(/tmp)
localhost - - [29/Jun/2008 09:32:07] "POST /RPC2 HTTP/1.0" 200 -
The first line of output is from the logging.debug() call inside list_contents(). The second line is from the server logging the request because logRequests is True.

Alternate Names

Sometimes the function names you use inside your modules or libraries are not the names you want to use in your external API. You might need to load a platform-specific implementation, build the service API dynamically based on a configuration file, or replace real functions with stubs for testing. If you want to register a function with an alternate name, pass the name as the second argument to register_function(), like this:

from SimpleXMLRPCServer import SimpleXMLRPCServer
import os

server = SimpleXMLRPCServer((‘localhost‘, 9000))

# Expose a function with an alternate name
def list_contents(dir_name):
    return os.listdir(dir_name)
server.register_function(list_contents, ‘dir‘)

try:
    print ‘Use Control-C to exit‘
    server.serve_forever()
except KeyboardInterrupt:
    print ‘Exiting‘
The client should now use the name dir() instead of list_contents():

import xmlrpclib

proxy = xmlrpclib.ServerProxy(‘http://localhost:9000‘)
print ‘dir():‘, proxy.dir(‘/tmp‘)
print ‘list_contents():‘, proxy.list_contents(‘/tmp‘)
Calling list_contents() results in an error, since the server no longer has a handler registered by that name.

$ python SimpleXMLRPCServer_alternate_name_client.py
dir(): [‘.s.PGSQL.5432‘, ‘.s.PGSQL.5432.lock‘, ‘.X0-lock‘, ‘.X11-unix‘, ‘ccc_exclude.1mkahl‘, ‘ccc_exclude.BKG3gb‘, ‘ccc_exclude.M5jrgo‘, ‘ccc_exclude.SPecwL‘, ‘com.hp.launchport‘, ‘emacs527‘, ‘hsperfdata_dhellmann‘, ‘launch-8hGHUp‘, ‘launch-RQnlcc‘, ‘launch-trsdly‘, ‘launchd-242.T5UzTy‘, ‘temp_textmate.V6YKzm‘, ‘var_backups‘]
list_contents():
Traceback (most recent call last):
  File "/Users/dhellmann/Documents/PyMOTW/in_progress/SimpleXMLRPCServer/SimpleXMLRPCServer_alternate_name_client.py", line 15, in <module>
    print ‘list_contents():‘, proxy.list_contents(‘/tmp‘)
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1147, in __call__
    return self.__send(self.__name, args)
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1437, in __request
    verbose=self.__verbose
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1201, in request
    return self._parse_response(h.getfile(), sock)
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 1340, in _parse_response
    return u.close()
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py", line 787, in close
    raise Fault(**self._stack[0])
xmlrpclib.Fault: <Fault 1: ‘<type \‘exceptions.Exception\‘>:method "list_contents" is not supported‘>
Dotted Names

Individual functions can be registered with names that are not normally legal for Python identifiers. For example, you can include ‘.’ in your names to separate the namespace in the service. This example extends our “directory” service to add “create” and “remove” calls. All of the functions are registered using the prefix “dir.” so that the same server can provide other services using a different prefix. One other difference in this example is that some of the functions return None, so we have to tell the server to translate the None values to a nil value (see XML-RPC Extensions).

from SimpleXMLRPCServer import SimpleXMLRPCServer
import os

server = SimpleXMLRPCServer((‘localhost‘, 9000), allow_none=True)

server.register_function(os.listdir, ‘dir.list‘)
server.register_function(os.mkdir, ‘dir.create‘)
server.register_function(os.rmdir, ‘dir.remove‘)

try:
    print ‘Use Control-C to exit‘
    server.serve_forever()
except KeyboardInterrupt:
    print ‘Exiting‘
To call the service functions in the client, simply refer to them with the dotted name, like so:

import xmlrpclib

proxy = xmlrpclib.ServerProxy(‘http://localhost:9000‘)
print ‘BEFORE       :‘, ‘EXAMPLE‘ in proxy.dir.list(‘/tmp‘)
print ‘CREATE       :‘, proxy.dir.create(‘/tmp/EXAMPLE‘)
print ‘SHOULD EXIST :‘, ‘EXAMPLE‘ in proxy.dir.list(‘/tmp‘)
print ‘REMOVE       :‘, proxy.dir.remove(‘/tmp/EXAMPLE‘)
print ‘AFTER        :‘, ‘EXAMPLE‘ in proxy.dir.list(‘/tmp‘)
and (assuming you don’t have a /tmp/EXAMPLE file on your system) the output for the sample client script looks like:

$ python SimpleXMLRPCServer_dotted_name_client.py
BEFORE       : False
CREATE       : None
SHOULD EXIST : True
REMOVE       : None
AFTER        : False
Arbitrary Names

A less useful, but potentially interesting feature is the ability to register functions with names that are otherwise invalid attribute names. This example service registers a function with the name “multiply args”.

from SimpleXMLRPCServer import SimpleXMLRPCServer

server = SimpleXMLRPCServer((‘localhost‘, 9000))

def my_function(a, b):
    return a * b
server.register_function(my_function, ‘multiply args‘)

try:
    print ‘Use Control-C to exit‘
    server.serve_forever()
except KeyboardInterrupt:
    print ‘Exiting‘
Since the registered name contains a space, we can’t use dot notation to access it directly from the proxy. We can, however, use getattr().

import xmlrpclib

proxy = xmlrpclib.ServerProxy(‘http://localhost:9000‘)
print getattr(proxy, ‘multiply args‘)(5, 5)
You should avoid creating services with names like this, though. This example is provided not necessarily because it is a good idea, but because you may encounter existing services with arbitrary names and need to be able to call them.

$ python SimpleXMLRPCServer_arbitrary_name_client.py
25
Exposing Methods of Objects

The earlier sections talked about techniques for establishing APIs using good naming conventions and namespacing. Another way to incorporate namespacing into your API is to use instances of classes and expose their methods. We can recreate the first example using an instance with a single method.

from SimpleXMLRPCServer import SimpleXMLRPCServer
import os
import inspect

server = SimpleXMLRPCServer((‘localhost‘, 9000), logRequests=True)

class DirectoryService:
    def list(self, dir_name):
        return os.listdir(dir_name)

server.register_instance(DirectoryService())

try:
    print ‘Use Control-C to exit‘
    server.serve_forever()
except KeyboardInterrupt:
    print ‘Exiting‘
A client can call the method directly:

import xmlrpclib

proxy = xmlrpclib.ServerProxy(‘http://localhost:9000‘)
print proxy.list(‘/tmp‘)
and receive output like:

$ python SimpleXMLRPCServer_instance_client.py
[‘.s.PGSQL.5432‘, ‘.s.PGSQL.5432.lock‘, ‘.X0-lock‘, ‘.X11-unix‘, ‘ccc_exclude.1mkahl‘,
‘ccc_exclude.BKG3gb‘, ‘ccc_exclude.M5jrgo‘, ‘ccc_exclude.SPecwL‘, ‘com.hp.launchport‘,
‘emacs527‘, ‘hsperfdata_dhellmann‘, ‘launch-8hGHUp‘, ‘launch-RQnlcc‘, ‘launch-trsdly‘,
‘launchd-242.T5UzTy‘, ‘temp_textmate.XNiIdy‘, ‘var_backups‘]
We’ve lost the “dir.” prefix for the service, though, so let’s define a class to let us set up a service tree that can be invoked from clients.

from SimpleXMLRPCServer import SimpleXMLRPCServer
import os
import inspect

server = SimpleXMLRPCServer((‘localhost‘, 9000), logRequests=True)

class ServiceRoot:
    pass

class DirectoryService:
    def list(self, dir_name):
        return os.listdir(dir_name)

root = ServiceRoot()
root.dir = DirectoryService()

server.register_instance(root, allow_dotted_names=True)

try:
    print ‘Use Control-C to exit‘
    server.serve_forever()
except KeyboardInterrupt:
    print ‘Exiting‘
By registering the instance of ServiceRoot with allow_dotted_names enabled, we give the server permission to walk the tree of objects when a request comes in to find the named method using getattr().

import xmlrpclib

proxy = xmlrpclib.ServerProxy(‘http://localhost:9000‘)
print proxy.dir.list(‘/tmp‘)
$ python SimpleXMLRPCServer_instance_dotted_names_client.py
[‘.s.PGSQL.5432‘, ‘.s.PGSQL.5432.lock‘, ‘.X0-lock‘, ‘.X11-unix‘, ‘ccc_exclude.1mkahl‘, ‘ccc_exclude.BKG3gb‘, ‘ccc_exclude.M5jrgo‘, ‘ccc_exclude.SPecwL‘, ‘com.hp.launchport‘, ‘emacs527‘, ‘hsperfdata_dhellmann‘, ‘launch-8hGHUp‘, ‘launch-RQnlcc‘, ‘launch-trsdly‘, ‘launchd-242.T5UzTy‘, ‘temp_textmate.adghkQ‘, ‘var_backups‘]
Dispatching Calls Yourself

By default, register_instance() finds all callable attributes of the instance with names not starting with ‘_‘ and registers them with their name. If you want to be more careful about the exposed methods, you could provide your own dispatching logic. For example:

from SimpleXMLRPCServer import SimpleXMLRPCServer
import os
import inspect

server = SimpleXMLRPCServer((‘localhost‘, 9000), logRequests=True)

def expose(f):
    "Decorator to set exposed flag on a function."
    f.exposed = True
    return f

def is_exposed(f):
    "Test whether another function should be publicly exposed."
    return getattr(f, ‘exposed‘, False)

class MyService:
    PREFIX = ‘prefix‘

    def _dispatch(self, method, params):
        # Remove our prefix from the method name
        if not method.startswith(self.PREFIX + ‘.‘):
            raise Exception(‘method "%s" is not supported‘ % method)

        method_name = method.partition(‘.‘)[2]
        func = getattr(self, method_name)
        if not is_exposed(func):
            raise Exception(‘method "%s" is not supported‘ % method)

        return func(*params)

    @expose
    def public(self):
        return ‘This is public‘

    def private(self):
        return ‘This is private‘

server.register_instance(MyService())

try:
    print ‘Use Control-C to exit‘
    server.serve_forever()
except KeyboardInterrupt:
    print ‘Exiting‘
The public() method of MyService is marked as exposed to the XML-RPC service while private() is not. The _dispatch() method is invoked when the client tries to access a function that is part of MyService. It first enforces the use of a prefix (“prefix.” in this case, but you can use any string). Then it requires the function to have an attribute called exposed with a true value. The exposed flag is set on a function using a decorator for convenience.

Here are a few sample client calls:

import xmlrpclib

proxy = xmlrpclib.ServerProxy(‘http://localhost:9000‘)
print ‘public():‘, proxy.prefix.public()
try:
    print ‘private():‘, proxy.prefix.private()
except Exception, err:
    print ‘ERROR:‘, err
try:
    print ‘public() without prefix:‘, proxy.public()
except Exception, err:
    print ‘ERROR:‘, err
and the resulting output, with the expected error messages trapped and reported:

$ python SimpleXMLRPCServer_instance_with_prefix_client.py
public(): This is public
private(): ERROR: <Fault 1: ‘<type \‘exceptions.Exception\‘>:method "prefix.private" is not supported‘>
public() without prefix: ERROR: <Fault 1: ‘<type \‘exceptions.Exception\‘>:method "public" is not supported‘>
There are several other ways to override the dispatching mechanism, including subclassing directly from SimpleXMLRPCServer. Check out the docstrings in the module for more details.

Introspection API

As with many network services, it is possible to query an XML-RPC server to ask it what methods it supports and learn how to use them. SimpleXMLRPCServer includes a set of public methods for performing this introspection. By default they are turned off, but can be enabled with register_introspection_functions(). You can add explicit support for system.listMethods() and system.methodHelp() by defining _listMethods() and _methodHelp() on your service class. For example,

from SimpleXMLRPCServer import SimpleXMLRPCServer, list_public_methods
import os
import inspect

server = SimpleXMLRPCServer((‘localhost‘, 9000), logRequests=True)
server.register_introspection_functions()

class DirectoryService:

    def _listMethods(self):
        return list_public_methods(self)

    def _methodHelp(self, method):
        f = getattr(self, method)
        return inspect.getdoc(f)

    def list(self, dir_name):
        """list(dir_name) => [<filenames>]

        Returns a list containing the contents of the named directory.
        """
        return os.listdir(dir_name)

server.register_instance(DirectoryService())

try:
    print ‘Use Control-C to exit‘
    server.serve_forever()
except KeyboardInterrupt:
    print ‘Exiting‘
In this case, the convenience function list_public_methods() scans an instance to return the names of callable attributes that do not start with ‘_‘. You can redefine _listMethods() to apply whatever rules you like. Similarly, for this basic example _methodHelp() returns the docstring of the function, but could be written to build a help string from another source.

This client queries the server and reports on all of the publicly callable methods.

import xmlrpclib

proxy = xmlrpclib.ServerProxy(‘http://localhost:9000‘)
for method_name in proxy.system.listMethods():
    print ‘=‘ * 60
    print method_name
    print ‘-‘ * 60
    print proxy.system.methodHelp(method_name)
    print
Notice that the system methods are included in the results.

$ python SimpleXMLRPCServer_introspection_client.py
============================================================
list
------------------------------------------------------------
list(dir_name) => [<filenames>]

Returns a list containing the contents of the named directory.

============================================================
system.listMethods
------------------------------------------------------------
system.listMethods() => [‘add‘, ‘subtract‘, ‘multiple‘]

Returns a list of the methods supported by the server.

============================================================
system.methodHelp
------------------------------------------------------------
system.methodHelp(‘add‘) => "Adds two integers together"

Returns a string containing documentation for the specified method.

============================================================
system.methodSignature
------------------------------------------------------------
system.methodSignature(‘add‘) => [double, int, int]

Returns a list describing the signature of the method. In the
above example, the add method takes two integers as arguments
and returns a double result.

This server does NOT support system.methodSignature.
时间: 2024-10-21 20:28:25

xmlrpc.server.SimpleXMLRPCServer的相关文章

python xmlrpc

rpc 协议 RPC = Remote Procedure Call Protocol,即远程过程调用协议. xml rpc 协议 使用http协议作为传输协议,使用xml文本传输命令和数据的一种协议.分成client和server. python 中的xmlrpc 使用Anaconda3安装的时候,已经在Lib下安装了xmlrpc,里面包含了client.py和server.py,直接import就可以使用了. 简单例子 server端 import xmlrpc.server class M

《python参考手册(第四版)》【PDF】下载

<python参考手册(第四版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382222 内容介绍 本书是权威的Python语言参考指南,内容涉及核心Python语言和Python库的最重要部分.本书内容简洁扼要.可读性强,书中还包括了一些没有在Python官方文档或其他资料中出现过的一些高级的主题. 这一版在内容上进行了全面更新,介绍了Python 2.6和Python 3新引入的编程语言特性和库模块,同时还分析了Python程序

参考手册目录__第二部分

参考手册目录__第一部分 参考手册目录__第二部分 参考手册目录__第三部分 第二部分: python库------164 第 12 章: 内置函数和异常------164 12.1 内置函数和类型------172 12.2 内置异常------172 12.2.1 异常基类------173 12.2.2 预定义的异常类------173 12.3 内置警告------176 12.4 future_builtins------176 第 13 章: Python运行时的服务------17

用XMLRPC开服务进行server/client通信

本文讲一下如何用python的xmlrpc开服务,进行server/client的通信. 应用场景:1)需多client访问应用程序给予应答情况--网页服务:  2)数据极大,希望加载一次,后面只用方法调用 解决方案:  开两个服务,一个数据服务,一个网络服务:  数据服务端加载数据,网络服务端调用数据,并将结果显示在网络服务中:  外部调用网络服务返回结果: 应用工具:xmlrpc,本文中以python 2.7.3的xmlrpclib为例,其他语言也有相应接口 下面分别说明. 1. 数据端 在

XML-RPC远程方法调用

一.简介 XML-RPC的全称是XML Remote Procedure Call,即XML远程方法调用. 它是一套允许运行在不同操作系统.不同环境的程序实现基于Internet过程调用的规范和一系列的实现. 这种远程过程调用使用http作为传输协议,XML作为传送信息的编码格式. Xml-Rpc的定义尽可能的保持了简单,但同时能够传送.处理.返回复杂的数据结构. xml rpc使用http协议做为传输协议的rpc机制,使用xml文本的方式传输命令和数据. 一个rpc系统,必然包括2个部分: 1

Python的招牌菜xmlrpc

一.简单介绍 为了解决在系统的80port提供RPC的服务.而又不影响正在运行的WEB服务.人们想出了用HTTP协议传输RPC包的办法.对于差点儿是专门用于传输文本的HTTP协议.要在其上传输RPC封包.最方便的方法莫过于把RPC封包编码成文本形式--比如XML文件. XML- RPC(http://www.xml-rpc.com)是由美国UserLand公司指定的一个RPC协议.它将RPC信息封包编码为XML,然后通过 HTTP传输封包: 简单的理解: 将数据定义为xml格式.通过http协议

Python中使用XMLRPC(入门)

一.简介 RPC是Remote Procedure Call的缩写,翻译成中文为:远程方法调用. 它是一种在本地机器上调用远端机器上的一个过程(方法)的技术,这个过程也被大家称为“分布式计算”,是为了提高各个分立机器的“互操作性”而发明出来的技术. XML-RPC的全称是XML Remote Procedure Call,即XML远程方法调用. 它是一套允许运行在不同操作系统.不同环境的程序实现基于Internet过程调用的规范和一系列的实现.这种远程过程调用使用http作为传输协议,XML作为

Python中的XMLRPC(Calendar)

XMLRPC服务器端代码,定义了三个方法名,getMonth获取所给月份的日历,getYear获取一年的日历,getDict测试返回字典的效果. xmlrpc_server.py: #!/usr/bin/python # coding: utf-8 import calendar, SimpleXMLRPCServer, time, string, os #创建 Server 对象 class Calendar: def getMonth(self, year, month): if(type(

python xmlrpc模块

简介 rpc:远程过程调用协议.简单的来说就是客户端可以很方便得远程调用服务端的接口程序,而不用管底层是如何实现的. XML-RPC的全称是XML Remote Procedure Call,即XML(标准通用标记语言下的一个子集)远程过程调用.它是一套允许运行在不同操作系统.不同环境的程序实现基于Internet过程调用的规范和一系列的实现.这种远程过程调用使用http作为传输协议,XML作为传送信息的编码格式.Xml-Rpc的定义尽可能的保持了简单,但同时能够传送.处理.返回复杂的数据结构.