Python 开发与测试 Webservice(SOAP)-Win

2023-05-16

WebService是一种跨编程语言和跨操作系统平台的远程调用技术。


> 理解webservice

1.从表面上看,WebService就是一个应用程序向外界暴露出一个能通过Web进行调用的API,也就是说能用编程的方法通过Web来调用这个应用程序。我们把调用这个WebService的应用程序叫做客户端,而把提供这个WebService的应用程序叫做服务端。

2.从深层次看,WebService是建立可互操作的分布式应用程序的新平台,是一个平台,是一套标准。它定义了应用程序如何在Web上实现互操作性,你可以用任何你喜欢的语言,在任何你喜欢的平台上写Web service ,只要我们可以通过Web service标准对这些服务进行查询和访问。

3.Web Service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的交互操作的应用程序。 [1]

4.Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。Web Service是自描述、 自包含的可用网络模块, 可以执行具体的业务功能。Web Service也很容易部署, 因为它们基于一些常规的产业标准以及已有的一些技术,诸如标准通用标记语言下的子集XML、HTTP。Web Service减少了应用接口的花费。Web Service为整个企业甚至多个组织之间的业务流程的集成提供了一个通用机制。

> Web服务的三个核心

  • 1、Soap:
    SOAP(Simple Object Access Protocol,简单对象访问协议)是一个基于xml的协议,用于在分步的应用程序都可以识别。另外,SOAP本身没有定义任何程序语言,这使得SOAP能够以消息的形式传递到各种远程系统中。

    SOAP所使用的传输协议,可以是HTTP,SMTP,POP3,JMS。

    SOAP包括了4部分:
    01.“SOAP封装(Envelope)”:
    定义一个描述信息描述的内容是什么,是谁发送的,谁应当处理他,以及如何处理他们的框架。

    02.“SOAP编码规则”:
    用于表示应用程序需要使用的数据类型的实例。

    03.“SOAP RPC":
    表示远程过程中调用和应答的协定。

    04.“SOPA绑定”:
    使用底层协议交换信息。

  • 2.WSDL:
    WSDL(Web Service Description Language,web服务描述语言)是一个XML文档,他以一种和具体语言无关的抽象方式定义了给定web服务收发者的有关操作和消息。

  • 3.UDDI:
    UDDI(Universal Description Discovery and Integration,统一描述发现和集成协议)是一个规范,定义了与web服务相关的信息的发布,发现和管理。
    END

> 看懂wsdl文件

只有看懂wsdl文件才能去调用soap类型的web服务,下面以YCS项目为例子的wsdl文件:
image
解释:首先我们可以看到服务的地址为:http://47.106.68.247/ycsyth/webservices/ycsbizService,对应wsdl文件的地址为http://47.106.68.247/ycsyth/webservices/ycsbizService?wsdl,地址的前缀为soap,说明这个服务是基于soap1.1版本的,然后我们可以看到服务的名称为IYcsBizServiceService,IYcsBizServiceService绑定的Port为IYcsBizServicePort,然后我们找到IYcsBizServicePort绑定的类型为IYcsBizService(portType name=“IYcsBizService”),从IYcsBizService中我们可以看到,支持一个方法叫做doService,关于doService的具体参数的信息看complexType name=“doService”。

> Python 库选择

服务端开发:

针对Python的WebService开发,开发者讨论最多的库是soaplib(官方地址:http://soaplib.github.io/soaplib/2_0/index.html),但从其官网可知,其最新版本“soaplib-2.0.0-beta2”从2011年3月发布后就不再进行更新了。通过阅读soaplib的官方文档,可知其不再维护后已经转向了一个新的项目:rpclib(官方地址:http://github.com/arskom/rpclib)进行后续开发,但在rpclib的readme中,介绍了rpclib已经更名为spyne,并将持续进行更新,so,那就选用spyne进行开发了。

spyne 官方文档:http://spyne.io/docs/2.10/index.html

spyne github:https://github.com/arskom/spyne

  • spyne 安装:
pip install spyne
  • lxml 安装:
pip install lxml

或者下载与python匹配的版本安装包 https://pypi.python.org/pypi/lxml/3.6.0 进行安装,如 lxml-3.6.0.win-amd64-py2.7.exe (md5)

客户端开发

客户端调用WebService一般应用suds库。

使用参考文档:https://fedorahosted.org/suds/wiki/Documentation

  • suds 安装:
pip install suds

> 知识拓展

Spyne Introduction

  • Protocols:协议
  • Protocols define the rules for transmission of structured data
  • Transports:传输
  • Transports, also protocols themselves, encapsulate protocol data in their free-form data sections.
  • Models:模式
  • Types like Unicode, Integer or ByteArray are all models. They reside in the spyne.model package.
  • Interface Documents:接口文档
  • Interface documents provide a machine-readable description of the expected input and output of the exposed method calls.
  • Serializers:序列化对象
  • Serializers are currently not distinguished in Spyne code. They are the protocol-specific representations of a serialized Python object.

How your code is wrapped?

  • step1:

  • Your code is inside @rpc-wrapped methods in ServiceBase subclasses.

  • step2:

  • The ServiceBase subclasses in turn are wrapped by an Application instance.

  • The Application instantiation is used to assign input and output protocols to the exposed methods.

  • step3:

  • The Application instance is finally wrapped by a client or server transport that takes the responsibility of moving the bits around.

  • step4:

  • Deploying the service using Soap via Wsgi


> 代码实例–(结构1)

目录结构

webservice
	client.py
	serve.py

使用Python实现服务端

server.py 服务端启动文件
# -*- coding: utf-8 -*-
 
"""
preference:
    http://spyne.io/docs/2.10/index.html
    https://github.com/arskom/spyne/blob/master/examples/helloworld_soap.py
 
This is a simple HelloWorld example to show the basics of writing
a webservice using spyne, starting a server, and creating a service
client.
Here's how to call it using suds:
 
#>>> from suds.client import Client
#>>> hello_client = Client('http://localhost:8000/?wsdl')
#>>> hello_client.service.say_hello('punk', 5)
(stringArray){
   string[] =
      "Hello, punk",
      "Hello, punk",
      "Hello, punk",
      "Hello, punk",
      "Hello, punk",
 }
#>>>
 
"""
# Application is the glue between one or more service definitions, interface and protocol choices.
from spyne import Application
# @rpc decorator exposes methods as remote procedure calls
# and declares the data types it accepts and returns
from spyne import rpc
# spyne.service.ServiceBase is the base class for all service definitions.
from spyne import ServiceBase
# The names of the needed types for implementing this service should be self-explanatory.
from spyne import Iterable, Integer, Unicode
 
from spyne.protocol.soap import Soap11
# Our server is going to use HTTP as transport, It’s going to wrap the Application instance.
from spyne.server.wsgi import WsgiApplication
 
 
# step1: Defining a Spyne Service
class HelloWorldService(ServiceBase):
    @rpc(Unicode, Integer, _returns=Iterable(Unicode))
    def say_hello(self, name, times):
        """Docstrings for service methods appear as documentation in the wsdl.
        <b>What fun!</b>
        @param name: the name to say hello to
        @param times: the number of times to say hello
        @return  When returning an iterable, you can use any type of python iterable. Here, we chose to use generators.
        """
 
        for i in range(times):
            yield u'Hello, %s' % name
 
 
# step2: Glue the service definition, input and output protocols
soap_app = Application([HelloWorldService], 'spyne.examples.hello.soap',
                       in_protocol=Soap11(validator='lxml'),
                       out_protocol=Soap11())
 
# step3: Wrap the Spyne application with its wsgi wrapper
wsgi_app = WsgiApplication(soap_app)
 
if __name__ == '__main__':
    import logging
 
    from wsgiref.simple_server import make_server
 
    # configure the python logger to show debugging output
    # logging.basicConfig(level=logging.DEBUG)
    # logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG)
 
    # logging.info("listening to http://127.0.0.1:8000")
    # logging.info("wsdl is at: http://localhost:8000/?wsdl")
 
    # step4:Deploying the service using Soap via Wsgi
    # register the WSGI application as the handler to the wsgi server, and run the http server
    print('WebService Started')
    server = make_server('127.0.0.1', 8000, wsgi_app)
    server.serve_forever()

检查服务

服务端运行后,

访问浏览器检查服务 http://localhost:8000/?wsdl

浏览器中输出wsdl文件:
image

使用Python实现客户端

client.py 客户端接口
# -*- coding: utf-8 -*-
 
from suds.client import Client  # 导入suds.client 模块下的Client类
 
wsdl_url = "http://localhost:8000/?wsdl"
 
 
def say_hello_test(url, name, times):
    client = Client(url)                    # 创建一个webservice接口对象
    resp = client.service.say_hello(name, times)
    print(resp)
    # client.service.say_hello(name, times)   # 调用这个接口下的getMobileCodeInfo方法,并传入参数
    # req = str(client.last_sent())           # 保存请求报文,因为返回的是一个实例,所以要转换成str
    # response = str(client.last_received())  # 保存返回报文,返回的也是一个实例
    # print (req)       # 打印请求报文
    # print (response)  # 打印返回报文
 
if __name__ == '__main__':
    say_hello_test(wsdl_url, 'Milton', 2)

接口测试

启动服武器

image

执行客户端

image

客户端结果如下

(stringArray){
   string[] = 
      "Hello, Milton",
      "Hello, Milton",
 }

> 代码实例–(结构2)

目录结构

webservice
	client
		client.py
	server
		app.py
		service.py

使用Python实现服务端

service.py 服务端启动文件
# -*- coding: utf-8 -*-
 
"""
preference:
    http://spyne.io/docs/2.10/index.html
    https://github.com/arskom/spyne/blob/master/examples/helloworld_soap.py
 
This is a simple HelloWorld example to show the basics of writing
a webservice using spyne, starting a server, and creating a service
client.
Here's how to call it using suds:
 
#>>> from suds.client import Client
#>>> hello_client = Client('http://localhost:8000/?wsdl')
#>>> hello_client.service.say_hello('punk', 5)
(stringArray){
   string[] =
      "Hello, punk",
      "Hello, punk",
      "Hello, punk",
      "Hello, punk",
      "Hello, punk",
 }
#>>>
 
"""
import json
import os

# Application is the glue between one or more service definitions, interface and protocol choices.
# 应用程序是一个或多个服务定义、接口和协议选择之间的粘合剂
from spyne import Application
# @rpc decorator exposes methods as remote procedure calls 装饰器将方法公开为远程过程调用
# and declares the data types it accepts and returns 并声明它接受和返回的数据类型
from spyne import rpc
# spyne.service.ServiceBase is the base class for all service definitions.
from spyne import ServiceBase
# The names of the needed types for implementing this service should be self-explanatory.
# 实现该服务所需类型的名称应该是不言自明的
from spyne import Iterable, Integer, Unicode
 
from spyne.protocol.soap import Soap11
# Our server is going to use HTTP as transport, It’s going to wrap the Application instance.
from spyne.server.wsgi import WsgiApplication

from app import PyWebService    #注意:此处引用app.py文件内的PyWebService类


#step1: Defining a Spyne Service
# class PyWebService(ServiceBase):
    
#     @rpc(Unicode, Integer, _returns=Iterable(Unicode))
#     def say_hello(self, name, times):
#         """Docstrings for service methods appear as documentation in the wsdl.
#         <b>What fun!</b>
#         @param name: the name to say hello to
#         @param times: the number of times to say hello
#         @return  When returning an iterable, you can use any type of python iterable. Here, we chose to use generators.
#         """
        
#         for i in range(times):
#             return u'Hello, %s' % name
 
 
# step2: Glue the service definition, input and output protocols
soap_app = Application([PyWebService], 'PyWebService',
                       in_protocol=Soap11(validator='lxml'),
                       out_protocol=Soap11())
 
# step3: Wrap the Spyne application with its wsgi wrapper
wsgi_app = WsgiApplication(soap_app)
 
if __name__ == '__main__':
    import logging
 
    from wsgiref.simple_server import make_server
 
    # configure the python logger to show debugging output
    # logging.basicConfig(level=logging.DEBUG)
    # logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG)
 
    # logging.info("listening to http://127.0.0.1:8000")
    # logging.info("wsdl is at: http://localhost:8000/?wsdl")
    
    host = "127.0.0.1"
    port = 8000
    
    # step4:Deploying the service using Soap via Wsgi
    # register the WSGI application as the handler to the wsgi server, and run the http server
    server = make_server(host, port, wsgi_app)
    print('WebService Started')
    print('http://' + host + ':' + str(port) + '/?wsdl')
    server.serve_forever()
app.py webservice接口
# -*- coding: utf-8 -*-
import json

from spyne import ServiceBase, rpc, Double
from spyne import Integer, Unicode, String, Iterable

class User(object):
    def __init__(self, age, user_name):
        self.age = age
        self.user_name = user_name
        self.sex = 0

    def get_user_list(self, current_page, page_size):
        l = []
        for i in range(10):
            l.append({'age': self.age, 'sex': self.sex, 'user_name': self.user_name})
        return l


user_mgr = User(18, 'Tom')


class PyWebService(ServiceBase):
    ...

    @rpc(Unicode, Integer, _returns=Iterable(Unicode))
    def say_hello(self, name, times):
        """Docstrings for service methods appear as documentation in the wsdl.
        <b>What fun!</b>
        @param name: the name to say hello to
        @param times: the number of times to say hello
        @return  When returning an iterable, you can use any type of python iterable. Here, we chose to use generators.
        """        
        for i in range(times):
            return u'Hello, %s' % name

    @rpc(_returns=Unicode)
    def get_version(self):
        """
        获取系统版本
        :return:
        """
        return json.dumps({'version': 1.0})

    @rpc(Integer, Integer, _returns=Unicode)
    def get_user_list(self, current_page, page_size):
        """
        获取用户列表
        :return:
        """
        return json.dumps(user_mgr.get_user_list(current_page, page_size))

检查服务

服务端运行后,

访问浏览器检查服务 http://localhost:8000/?wsdl

浏览器中输出wsdl文件:
image

使用Python实现客户端

client.py 客户端接口
# -*- coding: utf-8 -*-
import json
from suds.client import Client  # 导入suds.client 模块下的Client类
 
wsdl_url = "http://localhost:8000/?wsdl"

def client_operation(url, name, times):
    client = Client(url)                    # 创建一个webservice接口对象
    print(client) #查看定义的所有方法与请求所需携带的参数,返回的Methods中即定义的方法,包括请求所需携带的参数与参数类型。

    resp = client.service.get_version()  # 调用这个接口下的get_version方法,无参数
    print(json.loads(resp))
    
    resp1 = client.service.say_hello(name, times)   # 调用这个接口下的getMobileCodeInfo方法,并传入参数
    print(str(resp1))

    resp2 = client.service.get_user_list(3,4)
    print(json.loads(resp2))
    
if __name__ == '__main__':
    client_operation(wsdl_url, 'Milton', 2)

接口测试

启动服武器

image

执行客户端

image

客户端结果如下

Suds ( https://fedorahosted.org/suds/ )  version: 1.1.1

Service ( PyWebService ) tns="PyWebService"
   Prefixes (1)
      ns0 = "PyWebService"
   Ports (1):
      (Application)
         Methods (3):
            get_user_list(xs:integer current_page, xs:integer page_size)
            get_version()
            say_hello(xs:string name, xs:integer times)
         Types (7):
            get_user_list
            get_user_listResponse
            get_version
            get_versionResponse
            say_hello
            say_helloResponse
            stringArray


{'version': 1.0}
(stringArray){
   string[] = 
      "H",
      "e",
      "l",
      "l",
      "o",
      ",",
      " ",
      "M",
      "i",
      "l",
      "t",
      "o",
      "n",
 }
[{'age': 18, 'sex': 0, 'user_name': 'Tom'}, {'age': 18, 'sex': 0, 'user_name': 'Tom'}, {'age': 18, 'sex': 0, 'user_name': 'Tom'}, {'age': 18, 'sex': 0, 'user_name': 'Tom'}, {'age': 18, 'sex': 0, 'user_name': 'Tom'}, {'age': 18, 'sex': 0, 'user_name': 'Tom'}, {'age': 18, 'sex': 0, 'user_name': 'Tom'}, {'age': 18, 'sex': 0, 'user_name': 'Tom'}, {'age': 18, 'sex': 0, 'user_name': 'Tom'}, {'age': 18, 'sex': 0, 'user_name': 'Tom'}]

参考连接:
http://47.106.68.247/ycsyth/webservices/ycsbizService?wsdl
https://blog.csdn.net/qq_33196814/article/details/122303882
https://www.cnblogs.com/guanfuchang/p/5985070.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 开发与测试 Webservice(SOAP)-Win 的相关文章

  • 带复杂命令启停功能的二自由度自动进样器

    给8051发送 34 Start E 34 后 系统开始工作 发送 34 Stop E 34 后 系统停止工作 与之前以串口中断为主线的控制逻辑不同 这里以定时器0中断为主线 其实也就是以系统序列动作为主线 并提高了串口中断的优先级 以实时
  • Python温度转换实例

    我的第一个程序 xff1a TempCovert py TemStr 61 input 34 请输入带有符号的温度值 xff1a 34 if TemStr 1 in 39 F 39 39 f 39 C 61 eval TemStr 0 1
  • 不同数据类型所占字节

    一 32位处理器 xff1a char xff1a 1个字节 char p xff1a 4个字节 int xff1a 4个字节 unsigned int xff1a 4个字节 double xff1a 8个字节 short xff1a 2个
  • 浏览器中输入www.baidu.com后发生了什么

    一道经典的面试题 xff1a 你输入网址后到页面显示出来 xff0c 中间发生了什么 xff1f 第一步 浏览器查找该域名的 IP 地址 第二步 浏览器根据解析得到的IP地址向 web 服务器发送一个 HTTP 请求 第三步 服务器收到请求
  • 交换机对数据帧的处理规则

    一 概述 以太网交换机对二层帧的转发处理比较复杂 xff0c 很多同事都不是很清楚 本文将对此问题进行总结 xff0c 并通过实验进行验证 二 交换机基本概念 在了解交换机转发规则之前 xff0c 我们先理解交换机的一些概念 xff0c 如
  • NAT详解

    NAT详解 1 概述 1 1 nat简介 NAT xff08 Network Address Translation xff0c 网络地址转换 xff09 是1994年提出的 它是一个IETF Internet Engineering Ta
  • FTP服务

    1 FTP简介 FTP是File Transfer Protocol xff08 文件传输协议 xff09 的英文简称 xff0c 而中文简称为 文传协议 用于Internet上的控制文件的双向传输 同时 xff0c 它也是一个应用程序 x
  • 从Linux服务器下载文件夹到本地

    1 使用scp命令 把本地的source txt文件拷贝到192 168 0 10机器上的 home work目录下 scp home work source txt root 64 192 168 0 10 home work 把192
  • 安卓开发——网络传输工具类HttpUtil(基于okhttp3)使用

    AndroStudio开发 xff1a 使用时需先导入okhttp3依赖 xff1a com squareup okhttp3 okhttp 3 4 1 依赖导入步骤 xff1a File ProjectStructure Dependen
  • 无人系统传感器导航

    文章目录 GPS 全球定位系统 Global positioning system RTK Real time kinematic 距离传感器超声波传感器激光测距传感器毫米波雷达 Lidar Light detection and rang
  • 深度相机选取建议:

    2020 9 4更新 xff1a 现在再回头来看TOF应该会是未来 xff0c 限制TOF发展的硬件问题正在慢慢解决 苹果的ipad上也加上了TOF xff08 用于AR xff09 xff0c ipone12上估计也会有 可能小米的mix
  • JavaHTTP请求工具类HTTPUtils

    HTTP 请求工具类 HTTPUtils xff0c 其中涉及 HTTP 请求相关的各种操作 xff0c 关于这些方法详细的介绍可以查看这些博客 x1f4ac 相关 博客文章 Java发起HTTP请求并解析JSON返回数据 https bl
  • YOLOV7语义分割(日后自用笔记)

    系统win10 本文只是根据readme文件走流程 xff0c 记录一些常用公式 RizwanMunawar yolov7 segmentation at 87b016cda50371d6e2824378d641c2d4417ea1c3 g
  • char型和int型之间的类型转换

    char转换为int型数据 通过赋值方式将char类型变量转换为int型变量 xff0c 变量值为char类型变量的ASCII码值 例如 xff1a int a 61 0 那么打印a的结果为48 xff0c 如果想要得到正确的数字 xff0
  • ROS出现Cannot find source file的错误和add_dependencies,add_executable,target_link_libraries三者先后顺序不对所造成的错误。

    出现上面这个报错 xff0c 往往是 CMakeLists txt中的问题 add executable server tutorial ws src dynamic tutorials src server cpp 这行代码的问题 xff
  • 利用python ast包,绘制python代码的调用关系图(可分析互相调用的多个py文件)

    我的目的是辅助代码阅读 xff08 也方便写文档 xff09 xff0c 因此不需要太详细的信息 xff0c 只需要看用户定义的函数的函数调用关系 文章目录 1 开源项目staticfg的安装和直接使用2 绘制python的简单调用关系图
  • 1.3 Ubuntu18.04 ROS udp server 通信实现

    Ubuntu18 04 ROS udp Server通信实现 此小节介绍udp Server收发数据 udp通信属于帧传输 xff0c 在帧传输过程中对于消息的次序和到达情况没有需求 xff0c 没有进行校验 xff0c 所以UDP属于不可
  • 1.4 Ubuntu18.04 ROS udp Client通信实现

    Ubuntu18 04 ROS udp Client通信实现 此小节介绍udp Client收发数据 udp通信属于帧传输 xff0c 在帧传输过程中对于消息的次序和到达情况没有需求 xff0c 没有进行校验 xff0c 所以UDP属于不可
  • 1.5 Ubuntu18.04 ROS tcp/ip服务器与Android tcp/ip客户端通信

    Ubuntu18 04 ROS tcp ip服务器与Android tcp ip客户端通信 此小节介绍ubuntu18 04 ros tcp ip服务端与Android tcp ip客户端通信 xff0c 此操作可以使用安卓系统开发ROS机
  • Kerloud Mini发布,做开源技术的拥护者

    产品介绍 云讷科技团队在无人系统软硬件上有多年的行业积累 xff0c 经过一年多的努力 xff0c 团队已经完全实现了自主化飞控软硬件的研发 xff0c 并具备了全套产业链生产能力 新出品的Kerloud Mini飞行控制器是针对低成本无人

随机推荐