SlideShare une entreprise Scribd logo
1  sur  4
Télécharger pour lire hors ligne
Python基于xmlrpc的webservice服务以及在odoo中的使用 
XML-RPC通过xml来传输RPC,在Python中提供了xmlrpclib模块进行了封装。参考文 
档https://docs.python.org/2/library/xmlrpclib.html 
一个简单的例子 
from SimpleXMLRPCServer import SimpleXMLRPCServer 
class HelloService: 
def sayHello(self, name): 
return "Hello " + name; 
def start_server(): 
obj = HelloService() 
server = SimpleXMLRPCServer(("localhost", 8080)) 
server.register_instance(obj) 
server.serve_forever() 
print "Server Started...." 
上面的例子作为服务端采用了SimpleXMLRPCServer,需要指定host和port即可。在这个例子里注册了一个对象实例,接下来看看 
客户端的写法 
import xmlrpclib 
def helloClient(): 
server = xmlrpclib.ServerProxy("http://localhost:8080") 
words = server.sayHello("Python") 
print "result: %s" % (words,) 
这样就完成了一个请求的过程。当然这只是一个很简单的例子,上面是注册实例,那么对象里面的方法都可以访问。同样也支持对 
函数的注册 
将函数作为服务发布 
def division(x, y): 
return x / y 
def server_reg_func(): 
server = SimpleXMLRPCServer(("localhost", 8080)) 
server.register_function(division, "division") 
server.serve_forever() 
print "Server Started...." 
将函数作为服务发布采用了方法register_function,需要传入参数函数和调用的名称。那么在客户端访问和上面例子基本一致, 
只需要调用函数名为注册的(division)即可server.division(2, 5)。上面的例子只注册了一个函数发布服务,在现实世界中可能 
会有多个服务,那也是支持的 
注册多个函数作为服务发布 
def server_multi_funcs(): 
server = SimpleXMLRPCServer(("localhost", 8080)) 
server.register_multicall_functions() 
server.register_function(division, "division") 
server.register_function(add, "add") 
server.serve_forever() 
print "Server Started...." 
这里新增了函数register_multicall_functions调用,那么就支持同时注册多个函数发布服务,这是在客户端需要做一些调整,不 
会直接返回结果而是将调用的结果作为实例返回 
def multi_fun_client(): 
server = xmlrpclib.ServerProxy("http://localhost:8080") 
multicall = xmlrpclib.MultiCall(server) 
try: 
multicall.division(2, 5) 
multicall.add(2, 0) 
result = multicall() 
print type(result) 
print "2/5=%d, 2+0=%d" % tuple(result)
print "2/5=%d, 2+0=%d" % tuple(result) 
except xmlrpclib.Fault as err: 
print "A fault occurred" 
print "Fault code: %d" % err.faultCode 
print "Fault string: %s" % err.faultString 
这里还显示了发生错误时相应的提示信息 
多线程的服务 
多线程服务也很简单,在服务端提供了相关的接口 
class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer): 
pass 
def server_thread(): 
server = ThreadXMLRPCServer(("localhost", 8080)) 
server.register_function(division, "division") 
server.serve_forever() 
这样服务端就能作为一个多线程处理请求,他会将每个请求一个线程进行处理 
多路径服务 
在前面的例子中我们都是在同一个端口下发布的服务,但是并没指定路径。对多路径的支持如下 
class RequestHandler(SimpleXMLRPCRequestHandler): 
rpc_paths = ('/','/hello') 
def server_path(): 
server = SimpleXMLRPCServer(("localhost", 8080), requestHandler=RequestHandler) 
server.register_function(add, "add") 
server.serve_forever() 
print "Server Started...." 
这里服务端新增了处理请求的Handler他会将根目录指向到/hello路径下,在客户端就可以用这个路径进行访问 
def path_client(): 
server = xmlrpclib.ServerProxy("http://localhost:8080/hello") 
print server.add(2, 5) 
二进制文件的读取 
在python官方DOC中提供了传输二进制文件的例子 
from SimpleXMLRPCServer import SimpleXMLRPCServer 
import xmlrpclib 
def python_logo(): 
with open("python_logo.jpg", "rb") as handle: 
return xmlrpclib.Binary(handle.read()) 
server = SimpleXMLRPCServer(("localhost", 8000)) 
print "Listening on port 8000..." 
server.register_function(python_logo, 'python_logo') 
server.serve_forever() 
客户端读取文件并写入本地 
import xmlrpclib 
proxy = xmlrpclib.ServerProxy("http://localhost:8000/") 
with open("fetched_python_logo.jpg", "wb") as handle: 
handle.write(proxy.python_logo().data) 
odoo中webservice的使用 
odoo中的webservice采用基于xmlrpc的实现提供了内置的实现,我们在暴露接口的时候只需要调用相关的方法就可以实现。 
获取用户信息 
传入dbname,name和password。返回uid。注意请求的路径为host:prot/xmlrpc/common
传入dbname,name和password。返回uid。注意请求的路径为host:prot/xmlrpc/common 
server_conf = xmlrpclib.ServerProxy("http://localhost:8069/xmlrpc/common") 
uid = server_conf.login("open_erp", "admin", "admin") 
新建一条记录 
对象的操纵请求路径都为host:prot/xmlrpc/object,需要传入参数dbname,uid,db_password可变的参数为需要创建对象的name 
属性(dili.pos.psam),方法,这里是新建(create),其他包括查询(search),读取(read),更新(write),删除(unlink) 
server = xmlrpclib.ServerProxy("http://localhost:8069/xmlrpc/object") 
psam = { 
'name' : 'abc', 
'rsa_public_key' : 'jjjjj' 
} 
result = server.execute("open_erp", uid, "root", "dili.pos.psam", "create", psam) 
查询、读取、更新和删除 
查询中支持查询参数(query_args)返回满足结果的id列表。 
读取中支持需要返回数据的字段(fields)返回满足条件的列表。 
更新则需要传入需要更新数据的编号列表,同时values对应了更改的编号返回执行结果True或False 
删除需要传入删除id列表,返回执行的结果True或False 
server = xmlrpclib.ServerProxy("http://localhost:8069/xmlrpc/object") 
query_args = [('name', '=', 'abc'), ('rsa_public_key', '=', 'jjjjj')] 
ids = server.execute("open_erp", uid, "root", "dili.pos.psam", "search", query_args) 
fields = ['name', 'rsa_public_key', 'psam_rsa'] 
datas = server.execute("open_erp", uid, "root", "dili.pos.psam", "read", ids, fields) 
values = {'name':'abcd'} 
success = server.execute("open_erp", uid, "root", "dili.pos.psam", "write", ids, values) 
success = server.execute("open_erp", uid, "root", "dili.pos.psam", "unlink", ids) 
odoo中实现简述 
接下来看看基于wsgi中的实现。我们可以从openerp-wsgi.py中工程启动使用了application函数 
application = openerp.service.wsgi_server.application 
在wigi_server.py中函数的定义指明了处理的方式 
def application(environ, start_response): 
if config['proxy_mode'] and 'HTTP_X_FORWARDED_HOST' in environ: 
return werkzeug.contrib.fixers.ProxyFix(application_unproxied)(environ, start_response) 
else: 
return application_unproxied(environ, start_response) 
在函数application_unproxied中采用了解析handler:wsgi_xmlrpc以及更多注册的。这里关注wsgi_xmlrpc 
def wsgi_xmlrpc(environ, start_response): 
""" Two routes are available for XML-RPC 
/xmlrpc/<service> route returns faultCode as strings. This is a historic 
violation of the protocol kept for compatibility. 
/xmlrpc/2/<service> is a new route that returns faultCode as int and is 
therefore fully compliant. 
""" 
if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'].startswith('/xmlrpc/'): 
length = int(environ['CONTENT_LENGTH']) 
data = environ['wsgi.input'].read(length) 
# Distinguish betweed the 2 faultCode modes 
string_faultcode = True 
if environ['PATH_INFO'].startswith('/xmlrpc/2/'): 
service = environ['PATH_INFO'][len('/xmlrpc/2/'):] 
string_faultcode = False
else: 
service = environ['PATH_INFO'][len('/xmlrpc/'):] 
params, method = xmlrpclib.loads(data) 
return xmlrpc_return(start_response, service, method, params, string_faultcode) 
这里有两点: 
1、只处理post请求和请求路径中有/xmlprc即处理基于xmlrpc的请求 
2、可以采用2中路径,区别是错误码返回int和字符串 
具体处理请求在函数xmlrpc_return中 
result = openerp.http.dispatch_rpc(service, method, params) 
在改方法中处理了几种service的情况 
if service_name == 'common': 
dispatch = openerp.service.common.dispatch 
elif service_name == 'db': 
dispatch = openerp.service.db.dispatch 
elif service_name == 'object': 
dispatch = openerp.service.model.dispatch 
elif service_name == 'report': 
dispatch = openerp.service.report.dispatch 
else: 
dispatch = openerp.service.wsgi_server.rpc_handlers.get(service_name) 
result = dispatch(method, params)

Contenu connexe

Tendances

如何学习Bash Shell
如何学习Bash Shell如何学习Bash Shell
如何学习Bash ShellLI Daobing
 
jsp基础速成精华讲解
jsp基础速成精华讲解jsp基础速成精华讲解
jsp基础速成精华讲解wensheng wei
 
J2ee面试知识
J2ee面试知识J2ee面试知识
J2ee面试知识yiditushe
 
Golang server design pattern
Golang server design patternGolang server design pattern
Golang server design pattern理 傅
 
Go语言web开发
Go语言web开发Go语言web开发
Go语言web开发Andy Shi
 
Mysql展示功能与源码对应
Mysql展示功能与源码对应Mysql展示功能与源码对应
Mysql展示功能与源码对应zhaolinjnu
 
Golangintro
GolangintroGolangintro
Golangintro理 傅
 
PHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming SkillsPHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming SkillsHo Kim
 
5, initialization & cleanup
5, initialization & cleanup5, initialization & cleanup
5, initialization & cleanupted-xu
 
SQL Loader & Bulk Insert 大量資料匯入工具
SQL Loader & Bulk Insert 大量資料匯入工具SQL Loader & Bulk Insert 大量資料匯入工具
SQL Loader & Bulk Insert 大量資料匯入工具HO-HSUN LIN
 
Ejb工作原理学习笔记
Ejb工作原理学习笔记Ejb工作原理学习笔记
Ejb工作原理学习笔记yiditushe
 
shell script introduction
shell script introductionshell script introduction
shell script introductionJie Jin
 
六步教你学会简单Rmi
六步教你学会简单Rmi六步教你学会简单Rmi
六步教你学会简单Rmiyiditushe
 
Mongodb
MongodbMongodb
Mongodbbj
 
Python 入门
Python 入门Python 入门
Python 入门kuco945
 
Jdbc中操作Blob、Clob等对象
Jdbc中操作Blob、Clob等对象Jdbc中操作Blob、Clob等对象
Jdbc中操作Blob、Clob等对象yiditushe
 
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践yiditushe
 
Monitor is all for ops
Monitor is all for opsMonitor is all for ops
Monitor is all for ops琛琳 饶
 
异步编程与浏览器执行模型
异步编程与浏览器执行模型异步编程与浏览器执行模型
异步编程与浏览器执行模型keelii
 

Tendances (20)

如何学习Bash Shell
如何学习Bash Shell如何学习Bash Shell
如何学习Bash Shell
 
jsp基础速成精华讲解
jsp基础速成精华讲解jsp基础速成精华讲解
jsp基础速成精华讲解
 
J2ee面试知识
J2ee面试知识J2ee面试知识
J2ee面试知识
 
Golang server design pattern
Golang server design patternGolang server design pattern
Golang server design pattern
 
Go语言web开发
Go语言web开发Go语言web开发
Go语言web开发
 
Mysql展示功能与源码对应
Mysql展示功能与源码对应Mysql展示功能与源码对应
Mysql展示功能与源码对应
 
Golangintro
GolangintroGolangintro
Golangintro
 
PHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming SkillsPHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming Skills
 
5, initialization & cleanup
5, initialization & cleanup5, initialization & cleanup
5, initialization & cleanup
 
SQL Loader & Bulk Insert 大量資料匯入工具
SQL Loader & Bulk Insert 大量資料匯入工具SQL Loader & Bulk Insert 大量資料匯入工具
SQL Loader & Bulk Insert 大量資料匯入工具
 
Ejb工作原理学习笔记
Ejb工作原理学习笔记Ejb工作原理学习笔记
Ejb工作原理学习笔记
 
shell script introduction
shell script introductionshell script introduction
shell script introduction
 
六步教你学会简单Rmi
六步教你学会简单Rmi六步教你学会简单Rmi
六步教你学会简单Rmi
 
Mongodb
MongodbMongodb
Mongodb
 
Python 入门
Python 入门Python 入门
Python 入门
 
Jdbc中操作Blob、Clob等对象
Jdbc中操作Blob、Clob等对象Jdbc中操作Blob、Clob等对象
Jdbc中操作Blob、Clob等对象
 
Node way
Node wayNode way
Node way
 
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践
 
Monitor is all for ops
Monitor is all for opsMonitor is all for ops
Monitor is all for ops
 
异步编程与浏览器执行模型
异步编程与浏览器执行模型异步编程与浏览器执行模型
异步编程与浏览器执行模型
 

En vedette

Veerendra_Patil_Technical_Skills_Details_
Veerendra_Patil_Technical_Skills_Details_Veerendra_Patil_Technical_Skills_Details_
Veerendra_Patil_Technical_Skills_Details_Veerendra Patil
 
Fisheries Debates Management Challenges
Fisheries Debates Management Challenges
Fisheries Debates Management Challenges
Fisheries Debates Management Challenges permissibleyout77
 
Python learn guide
Python learn guidePython learn guide
Python learn guiderobin yang
 
Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...
Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...
Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...AEM HUB
 
Eu africa summit
Eu africa summitEu africa summit
Eu africa summitrusnavy
 
linkedinculturedeck-150310163928-conversion-gate01
linkedinculturedeck-150310163928-conversion-gate01linkedinculturedeck-150310163928-conversion-gate01
linkedinculturedeck-150310163928-conversion-gate01Stephanie Walker
 
Creativity without comprise by Cleve Gibbon
Creativity without comprise by Cleve Gibbon Creativity without comprise by Cleve Gibbon
Creativity without comprise by Cleve Gibbon AEM HUB
 
Where are our Alumni now?
Where are our Alumni now?Where are our Alumni now?
Where are our Alumni now?Jordan Poulton
 
Choosing Page Orientation
Choosing Page OrientationChoosing Page Orientation
Choosing Page Orientationcbuzz001
 

En vedette (17)

december`15
december`15december`15
december`15
 
Veerendra_Patil_Technical_Skills_Details_
Veerendra_Patil_Technical_Skills_Details_Veerendra_Patil_Technical_Skills_Details_
Veerendra_Patil_Technical_Skills_Details_
 
Fisheries Debates Management Challenges
Fisheries Debates Management Challenges
Fisheries Debates Management Challenges
Fisheries Debates Management Challenges
 
Your first days
Your first daysYour first days
Your first days
 
action weekly March
action weekly Marchaction weekly March
action weekly March
 
HOSP PP
HOSP PPHOSP PP
HOSP PP
 
Python learn guide
Python learn guidePython learn guide
Python learn guide
 
Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...
Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...
Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...
 
Veerendra_2016_V2
Veerendra_2016_V2Veerendra_2016_V2
Veerendra_2016_V2
 
Action weekly ver.6
Action weekly ver.6Action weekly ver.6
Action weekly ver.6
 
Your self improvement
Your self improvementYour self improvement
Your self improvement
 
Eu africa summit
Eu africa summitEu africa summit
Eu africa summit
 
linkedinculturedeck-150310163928-conversion-gate01
linkedinculturedeck-150310163928-conversion-gate01linkedinculturedeck-150310163928-conversion-gate01
linkedinculturedeck-150310163928-conversion-gate01
 
Creativity without comprise by Cleve Gibbon
Creativity without comprise by Cleve Gibbon Creativity without comprise by Cleve Gibbon
Creativity without comprise by Cleve Gibbon
 
Where are our Alumni now?
Where are our Alumni now?Where are our Alumni now?
Where are our Alumni now?
 
Computer
ComputerComputer
Computer
 
Choosing Page Orientation
Choosing Page OrientationChoosing Page Orientation
Choosing Page Orientation
 

Similaire à Python xmlrpc-odoo

Flex 4.5 action data communication
Flex 4.5 action data communicationFlex 4.5 action data communication
Flex 4.5 action data communicationjexchan
 
用JAX-RS和Jersey完成RESTful Web Services
用JAX-RS和Jersey完成RESTful Web Services用JAX-RS和Jersey完成RESTful Web Services
用JAX-RS和Jersey完成RESTful Web Servicesjavatwo2011
 
MySQL源码分析.01.代码结构与基本流程
MySQL源码分析.01.代码结构与基本流程MySQL源码分析.01.代码结构与基本流程
MySQL源码分析.01.代码结构与基本流程Lixun Peng
 
PHP & MySQL 教學
PHP & MySQL 教學PHP & MySQL 教學
PHP & MySQL 教學Bo-Yi Wu
 
AWS Lambda Multi-Cloud Practices
AWS Lambda Multi-Cloud PracticesAWS Lambda Multi-Cloud Practices
AWS Lambda Multi-Cloud Practices康志強 大人
 
走马观花— Haskell Web 开发
走马观花— Haskell Web 开发走马观花— Haskell Web 开发
走马观花— Haskell Web 开发Gump Law
 
Android resource-management
Android resource-managementAndroid resource-management
Android resource-managementLucas Xu
 
运维系统开发与Rails 3页面开发实践
运维系统开发与Rails 3页面开发实践运维系统开发与Rails 3页面开发实践
运维系统开发与Rails 3页面开发实践Li JianYe
 
构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接 构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接 Renaun Erickson
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践self study
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践rewinx
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践Frank Cai
 
J2ee经典学习笔记
J2ee经典学习笔记J2ee经典学习笔记
J2ee经典学习笔记yiditushe
 
MongoDB for C# developer
MongoDB for C# developerMongoDB for C# developer
MongoDB for C# developerdianming.song
 
Ecma script edition5-小试
Ecma script edition5-小试Ecma script edition5-小试
Ecma script edition5-小试lydiafly
 
配置Oracle 10g 双向流复制
配置Oracle 10g 双向流复制配置Oracle 10g 双向流复制
配置Oracle 10g 双向流复制maclean liu
 
Introduction to Parse JavaScript SDK
Introduction to Parse JavaScript SDKIntroduction to Parse JavaScript SDK
Introduction to Parse JavaScript SDK維佋 唐
 
Asp.net mvc 培训
Asp.net mvc 培训Asp.net mvc 培训
Asp.net mvc 培训lotusprince
 

Similaire à Python xmlrpc-odoo (20)

Flex 4.5 action data communication
Flex 4.5 action data communicationFlex 4.5 action data communication
Flex 4.5 action data communication
 
用JAX-RS和Jersey完成RESTful Web Services
用JAX-RS和Jersey完成RESTful Web Services用JAX-RS和Jersey完成RESTful Web Services
用JAX-RS和Jersey完成RESTful Web Services
 
MySQL源码分析.01.代码结构与基本流程
MySQL源码分析.01.代码结构与基本流程MySQL源码分析.01.代码结构与基本流程
MySQL源码分析.01.代码结构与基本流程
 
PHP & MySQL 教學
PHP & MySQL 教學PHP & MySQL 教學
PHP & MySQL 教學
 
AWS Lambda Multi-Cloud Practices
AWS Lambda Multi-Cloud PracticesAWS Lambda Multi-Cloud Practices
AWS Lambda Multi-Cloud Practices
 
走马观花— Haskell Web 开发
走马观花— Haskell Web 开发走马观花— Haskell Web 开发
走马观花— Haskell Web 开发
 
Android resource-management
Android resource-managementAndroid resource-management
Android resource-management
 
运维系统开发与Rails 3页面开发实践
运维系统开发与Rails 3页面开发实践运维系统开发与Rails 3页面开发实践
运维系统开发与Rails 3页面开发实践
 
构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接 构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接
 
Structs2簡介
Structs2簡介 Structs2簡介
Structs2簡介
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践
 
J2ee经典学习笔记
J2ee经典学习笔记J2ee经典学习笔记
J2ee经典学习笔记
 
MongoDB for C# developer
MongoDB for C# developerMongoDB for C# developer
MongoDB for C# developer
 
Ecma script edition5-小试
Ecma script edition5-小试Ecma script edition5-小试
Ecma script edition5-小试
 
配置Oracle 10g 双向流复制
配置Oracle 10g 双向流复制配置Oracle 10g 双向流复制
配置Oracle 10g 双向流复制
 
Introduction to Parse JavaScript SDK
Introduction to Parse JavaScript SDKIntroduction to Parse JavaScript SDK
Introduction to Parse JavaScript SDK
 
Json知识分享
Json知识分享Json知识分享
Json知识分享
 
Asp.net mvc 培训
Asp.net mvc 培训Asp.net mvc 培训
Asp.net mvc 培训
 

Python xmlrpc-odoo

  • 1. Python基于xmlrpc的webservice服务以及在odoo中的使用 XML-RPC通过xml来传输RPC,在Python中提供了xmlrpclib模块进行了封装。参考文 档https://docs.python.org/2/library/xmlrpclib.html 一个简单的例子 from SimpleXMLRPCServer import SimpleXMLRPCServer class HelloService: def sayHello(self, name): return "Hello " + name; def start_server(): obj = HelloService() server = SimpleXMLRPCServer(("localhost", 8080)) server.register_instance(obj) server.serve_forever() print "Server Started...." 上面的例子作为服务端采用了SimpleXMLRPCServer,需要指定host和port即可。在这个例子里注册了一个对象实例,接下来看看 客户端的写法 import xmlrpclib def helloClient(): server = xmlrpclib.ServerProxy("http://localhost:8080") words = server.sayHello("Python") print "result: %s" % (words,) 这样就完成了一个请求的过程。当然这只是一个很简单的例子,上面是注册实例,那么对象里面的方法都可以访问。同样也支持对 函数的注册 将函数作为服务发布 def division(x, y): return x / y def server_reg_func(): server = SimpleXMLRPCServer(("localhost", 8080)) server.register_function(division, "division") server.serve_forever() print "Server Started...." 将函数作为服务发布采用了方法register_function,需要传入参数函数和调用的名称。那么在客户端访问和上面例子基本一致, 只需要调用函数名为注册的(division)即可server.division(2, 5)。上面的例子只注册了一个函数发布服务,在现实世界中可能 会有多个服务,那也是支持的 注册多个函数作为服务发布 def server_multi_funcs(): server = SimpleXMLRPCServer(("localhost", 8080)) server.register_multicall_functions() server.register_function(division, "division") server.register_function(add, "add") server.serve_forever() print "Server Started...." 这里新增了函数register_multicall_functions调用,那么就支持同时注册多个函数发布服务,这是在客户端需要做一些调整,不 会直接返回结果而是将调用的结果作为实例返回 def multi_fun_client(): server = xmlrpclib.ServerProxy("http://localhost:8080") multicall = xmlrpclib.MultiCall(server) try: multicall.division(2, 5) multicall.add(2, 0) result = multicall() print type(result) print "2/5=%d, 2+0=%d" % tuple(result)
  • 2. print "2/5=%d, 2+0=%d" % tuple(result) except xmlrpclib.Fault as err: print "A fault occurred" print "Fault code: %d" % err.faultCode print "Fault string: %s" % err.faultString 这里还显示了发生错误时相应的提示信息 多线程的服务 多线程服务也很简单,在服务端提供了相关的接口 class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer): pass def server_thread(): server = ThreadXMLRPCServer(("localhost", 8080)) server.register_function(division, "division") server.serve_forever() 这样服务端就能作为一个多线程处理请求,他会将每个请求一个线程进行处理 多路径服务 在前面的例子中我们都是在同一个端口下发布的服务,但是并没指定路径。对多路径的支持如下 class RequestHandler(SimpleXMLRPCRequestHandler): rpc_paths = ('/','/hello') def server_path(): server = SimpleXMLRPCServer(("localhost", 8080), requestHandler=RequestHandler) server.register_function(add, "add") server.serve_forever() print "Server Started...." 这里服务端新增了处理请求的Handler他会将根目录指向到/hello路径下,在客户端就可以用这个路径进行访问 def path_client(): server = xmlrpclib.ServerProxy("http://localhost:8080/hello") print server.add(2, 5) 二进制文件的读取 在python官方DOC中提供了传输二进制文件的例子 from SimpleXMLRPCServer import SimpleXMLRPCServer import xmlrpclib def python_logo(): with open("python_logo.jpg", "rb") as handle: return xmlrpclib.Binary(handle.read()) server = SimpleXMLRPCServer(("localhost", 8000)) print "Listening on port 8000..." server.register_function(python_logo, 'python_logo') server.serve_forever() 客户端读取文件并写入本地 import xmlrpclib proxy = xmlrpclib.ServerProxy("http://localhost:8000/") with open("fetched_python_logo.jpg", "wb") as handle: handle.write(proxy.python_logo().data) odoo中webservice的使用 odoo中的webservice采用基于xmlrpc的实现提供了内置的实现,我们在暴露接口的时候只需要调用相关的方法就可以实现。 获取用户信息 传入dbname,name和password。返回uid。注意请求的路径为host:prot/xmlrpc/common
  • 3. 传入dbname,name和password。返回uid。注意请求的路径为host:prot/xmlrpc/common server_conf = xmlrpclib.ServerProxy("http://localhost:8069/xmlrpc/common") uid = server_conf.login("open_erp", "admin", "admin") 新建一条记录 对象的操纵请求路径都为host:prot/xmlrpc/object,需要传入参数dbname,uid,db_password可变的参数为需要创建对象的name 属性(dili.pos.psam),方法,这里是新建(create),其他包括查询(search),读取(read),更新(write),删除(unlink) server = xmlrpclib.ServerProxy("http://localhost:8069/xmlrpc/object") psam = { 'name' : 'abc', 'rsa_public_key' : 'jjjjj' } result = server.execute("open_erp", uid, "root", "dili.pos.psam", "create", psam) 查询、读取、更新和删除 查询中支持查询参数(query_args)返回满足结果的id列表。 读取中支持需要返回数据的字段(fields)返回满足条件的列表。 更新则需要传入需要更新数据的编号列表,同时values对应了更改的编号返回执行结果True或False 删除需要传入删除id列表,返回执行的结果True或False server = xmlrpclib.ServerProxy("http://localhost:8069/xmlrpc/object") query_args = [('name', '=', 'abc'), ('rsa_public_key', '=', 'jjjjj')] ids = server.execute("open_erp", uid, "root", "dili.pos.psam", "search", query_args) fields = ['name', 'rsa_public_key', 'psam_rsa'] datas = server.execute("open_erp", uid, "root", "dili.pos.psam", "read", ids, fields) values = {'name':'abcd'} success = server.execute("open_erp", uid, "root", "dili.pos.psam", "write", ids, values) success = server.execute("open_erp", uid, "root", "dili.pos.psam", "unlink", ids) odoo中实现简述 接下来看看基于wsgi中的实现。我们可以从openerp-wsgi.py中工程启动使用了application函数 application = openerp.service.wsgi_server.application 在wigi_server.py中函数的定义指明了处理的方式 def application(environ, start_response): if config['proxy_mode'] and 'HTTP_X_FORWARDED_HOST' in environ: return werkzeug.contrib.fixers.ProxyFix(application_unproxied)(environ, start_response) else: return application_unproxied(environ, start_response) 在函数application_unproxied中采用了解析handler:wsgi_xmlrpc以及更多注册的。这里关注wsgi_xmlrpc def wsgi_xmlrpc(environ, start_response): """ Two routes are available for XML-RPC /xmlrpc/<service> route returns faultCode as strings. This is a historic violation of the protocol kept for compatibility. /xmlrpc/2/<service> is a new route that returns faultCode as int and is therefore fully compliant. """ if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'].startswith('/xmlrpc/'): length = int(environ['CONTENT_LENGTH']) data = environ['wsgi.input'].read(length) # Distinguish betweed the 2 faultCode modes string_faultcode = True if environ['PATH_INFO'].startswith('/xmlrpc/2/'): service = environ['PATH_INFO'][len('/xmlrpc/2/'):] string_faultcode = False
  • 4. else: service = environ['PATH_INFO'][len('/xmlrpc/'):] params, method = xmlrpclib.loads(data) return xmlrpc_return(start_response, service, method, params, string_faultcode) 这里有两点: 1、只处理post请求和请求路径中有/xmlprc即处理基于xmlrpc的请求 2、可以采用2中路径,区别是错误码返回int和字符串 具体处理请求在函数xmlrpc_return中 result = openerp.http.dispatch_rpc(service, method, params) 在改方法中处理了几种service的情况 if service_name == 'common': dispatch = openerp.service.common.dispatch elif service_name == 'db': dispatch = openerp.service.db.dispatch elif service_name == 'object': dispatch = openerp.service.model.dispatch elif service_name == 'report': dispatch = openerp.service.report.dispatch else: dispatch = openerp.service.wsgi_server.rpc_handlers.get(service_name) result = dispatch(method, params)