Python3 使用 zeep 调用 Web Service - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
atuocn
V2EX    Python

Python3 使用 zeep 调用 Web Service

  •  
  •   atuocn 2020-03-12 13:55:48 +08:00 4212 次点击
    这是一个创建于 2049 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Python3 使用 zeep 调用 Web Service

    Tags: Python3; zeep; SOAP; WSDL; suds

    前几天 Python3 下使用 suds 调用 Web Service,引用 wsdl 时出现类型错误。 得另外找一款 Python3 下的 SOAP Client 库了。Web Service 及 SOAP 协议红火的年代,Python3 还没出世。Python 的 SOAP 库基本上在 Python2 的时代就停止维护了。

    根据这两个链接1 2,调查了一下,大约 zeep 是目前 Python3 下 SOAP Client 的第一选择吧。

    Python3 下的 SOAP 库

    • zeep: 一个现代、高性能的 SOAP Client 库,还在积极维护。
    • suds-py3: suds 的 python3 移植版,仍有些小维护。另一个出境率高的 python3 移植版 suds-jurko 好几年没动了。
    • pysimplesoap: 具有 Client 和 wsgi Server 端。一套代码库支持 Py2 和 Py3。基本也没动了,偶尔一个小修复。
    • spyne: soaplib 几经改名后的作品。似乎目标不仅作为 SOAP 库,有更远大方向。官网说明运行在 python2 上,但 SOAP 子系统可用在 python3 下。

    WSDL 几个概念

    WSDL 是 Web Services Description Language ,以 XML 格式描述了 Web Service 的接口信息。

    通常象 C#这样的强类型语言,又有完善的 IDE 支持,开发不需要关心 WSDL 的内容,通过 IDE 导入,对象浏览即可差不多大致了解接口。

    但是 python 是动态语言,有时候还是需要大概看一下 wsdl 的内容,了解接口名称,参数等信息。

    • types: 定义 Web Service 所有数据类型。函数 /方法声明本身也在这里定义。函数 /方法用 Element 定义,其他的复杂数据类型则直接用 complexType 定义。
    • portType: 类似于 C#,Java 里的 interface。定义了一个接口包含的操作,以及操作包含的消息报文。
    • binding: 类似于 portType 的具体实现 class。不过这里的实现是指接口操作的具体承载的协议和消息格式。通常是使用 SOAP 协议来封装 Web Service.
    • port: 为 binding 指定一个具体地址,这样就定义了一个具体通信 Endpoint。一个 Endpoint 就相当于一个可以提供具体功能的实例对象。
    • service: 一组 port 或者说是 Endpoint, 相当于对象库。

    xml 的 namespace

    WSDL 是 xml 格式,会涉及到 xml 的 namespace 概念。

    一份 XML 中可能会引用多个标准组织的 schema,namespace 避免不同 schema 引入的元素命名冲突。

    <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://tempuri.org/" targetNamespace="http://tempuri.org/"> 

    xmlns 属性声明了引入的名字空间。上例中,xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/", 引入了名字空间 http://schemas.xmlsoap.org/wsdl/ ,并为该名字空间分配前缀名(prefix) wsdl 。 有名字空间前缀后,就可以通过 prefix:localpart 的方式使用 schema 里定义的名称。比如 wsdl:definitions 就是 http://schemas.xmlsoap.org/wsdl/名字空间下定义的 definitions 元素。

    wsdl:definitions 被称为 qualified name 。qualified name 在 xml 解析器中扩展成一个序对(namespace URI, local name),称为 expanded name 。一种非官方定义的,但被接受的表示法3: {http://schemas.xmlsoap.org/wsdl/}definitions

    targetNamespace 属性用来声明本 schema 文档所定义的元素所在的名字空间。 xmlns:tns="http://tempuri.org/" targetNamespace="http://tempuri.org/" 这句, targetNamespace 声明这份 WSDL 文档定义的 element, data type, 所在名字空间为 http://tempuri.org/ ,xmlns:tns 又声明,在本文档中,使用前缀 tns 表示名字空间 http://tempuri.org/

    targetNamespace 相当于 python 中 package 命名,xmlns 相当于 import package as alias

    查看 WSDL 接口信息

    浏览 WSDL 文件,看接口信息不太直观。zeep 提供一个方法查看 WSDL 接口信息。首先,pip 安装 zeep。

    注:下面有些示例代码直接 copy 自官方文档

    python -m zeep http://www.soapclient.com/xml/soapresponder.wsdl 

    该命令打印 wsdl 接口信息,可以把它保存在 txt 文件中,以便后面查看。输出的信息中 Prefixes 和 Global types,后面创建参数数据类型时可以用到。Global elements 或 Service 的 Port 节可以看到所有可用函数 /方法。

    调用 Web Service

    from zeep import Client client = Client('http://my-wsdl/wsdl') client.service.myoperation() 

    client.service 属性返回一个默认的 ServiceProxy 实例,自动连接了 WSDL 中第一个 Service 的第一个 Port。ServiceProxy 包装了 Web Service 调用。

    使用数据类型

    Web Service 中定义的各种参数数据类型,可以使用 dict 的方式,构造并传递。更方便的方法,通过辅助方法建。

    from zeep import Client client = Client('http://my-enterprise-endpoint.com') order_type = client.get_type('ns0:Order') order = order_type(number='1234', price=99) client.service.submit_order(user_id=1, order=order) 

    get_type 返回的是类对象。这里传入的数据类型名需要使用 WSDL 中的 qualified name,即带上前缀。ns0 是默认名字空间分配的前缀。也可使用 namespace 的扩展形式,例如:{http://my-wsdl/}Order。

    名字空间,名字空间前缀,数据类型信息可从上面提到的命令中查看。

    也可以使用 type_factory 创建数据对象:

    from zeep import Client client = Client('http://my-enterprise-endpoint.com') factory = client.type_factory('ns0') user = factory.User(id=1, name='John') order = factory.Order(number='1234', price=99) client.service.submit_order(user=user, order=order) 

    修改 Web Service 调用地址

    一个常见的场景是开发环境的 Web Service,部署到生产环境后 Web Service 地址变成生产环境地址。

    简单的办法,是 Client 创建对象时指定新的 wsdl 引用地址,新的 wsdl 包含了新的 Port 服务器地址定义。

    如果引入的 wsdl 和实际 web service 地址不同,比如把 wsdl 保存在项目文件中,从文件中引入。可以通过 create_service 创建新的 ServiceProxy 实例。

    service2=client.create_service('{http://my-wsdl/wsdl}myoperation','http://my-ws/ws') 

    create_service 第一个参数是 WSDL 中的 binding 名,第二个参数是服务调用地址。注意这边的 binding 名要带上 namespace 的扩展形式。文档上说使用 QName,实验来下使用前缀形式不行。 用上面查看 WSDL 接口信息的命令,输出的 binding 名也是扩展形式。

    Client 对象还提供了一个 bind 方法(不要和 WSDL 中的 binding 搞混了)创建 ServiceProxy 实例。WSDL 中定义了多个 Service/Port,zeep 默认使用 WSDL 中第一个 Service/Port,如果想用其他的 Service/Port 使用 bind 方法创建新 ServiceProxy。

    service2 = client.bind('SecondService', 'Port12') 

    使用 Http Proxy 或 SOCKS Proxy

    zeep 使用 request , 可以构造request.session,传入 zeep。如果使用 socks proxy 需要安装 request 的 socks 依赖。

    from zeep.import Client client = Client( 'http://my.own.sslhost.local/service?WSDL') client.transport.session.proxies = { 'http': 'foo.bar:3128', 'https': 'foo.bar:3128', } 

    修改 HTTP Header

    例如,修改 HTTP 的 User-Agent

    from zeep import Client,Settings settings=Settings(extra_http_headers={'User-Agent': 'Mozilla/5.0'}) client=Client('http://my-wsdl/wsdl',settings=settings) client.service.myoperation() 

    settings 支持 context manager,可以通过 with 语句,临时改变选项。

    from zeep import Client from zeep import xsd client = Client('http://my-endpoint.com/production.svc?wsdl') with client.settings(raw_respOnse=True): respOnse= client.service.myoperation() # response is now a regular requests.Response object assert response.status_code == 200 assert response.content 
    1 条回复    2020-03-13 13:42:40 +08:00
    yuu95
        1
    yuu95  
       2020-03-13 13:42:40 +08:00 via iPhone   1
    前两天用 python 写了个 webservice 客户端,刚开始用的 suds-py3 一直在报错,后来转到了 zeep
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     973 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 19:38 PVG 03:38 LAX 12:38 JFK 15:38
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86