我试图通过在Python2.7上使用SOAPpy调用一个使用SOAP请求的方法。该方法称为GetCursOnDate,并返回汇率。它需要一个日期参数。
我使用以下代码:
from SOAPpy import SOAPProxy
import datetime
date=datetime.datetime.now()
namespace ="http://web.cbr.ru/"
url = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx"
server = SOAPProxy(url,namespace)
print (date)
server.GetCursOnDate(date)但我得到了一个错误:
错误soap:Client: Server没有识别Header : GetCursOnDate的值。
为什么我会有这个错误?
发布于 2013-11-03 09:44:39
默认情况下,SOAPpy使用方法名作为header的值。如果运行以下代码,将在调试输出中看到该值:
from SOAPpy import SOAPProxy
from datetime import datetime
input = datetime.now()
namespace = "http://web.cbr.ru/"
url = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx"
proxy = SOAPProxy(url, namespace)
proxy.config.debug = 1
proxy.GetCursOnDate(input)调试显示如下:
*** Outgoing HTTP headers ***************************
POST /DailyInfoWebServ/DailyInfo.asmx HTTP/1.0
Host: www.cbr.ru
User-agent: SOAPpy 0.12.5 (http://pywebsvcs.sf.net)
Content-type: text/xml; charset=UTF-8
Content-length: 406
SOAPAction: "GetCursOnDate"
*****************************************************但是服务需要另一个值(http://web.cbr.ru/GetCursOnDate),您可以使用附加参数在代理上设置该值。以下代码清除错误:
from SOAPpy import SOAPProxy
from datetime import datetime
input = datetime.now()
namespace = "http://web.cbr.ru/"
url = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx"
soapaction = "http://web.cbr.ru/GetCursOnDate"
proxy = SOAPProxy(url, namespace = namespace, soapaction = soapaction)
proxy.config.debug = 1
proxy.GetCursOnDate(input)调试现在将显示如下:
*** Outgoing HTTP headers ***************************
POST /DailyInfoWebServ/DailyInfo.asmx HTTP/1.0
Host: www.cbr.ru
User-agent: SOAPpy 0.12.5 (http://pywebsvcs.sf.net)
Content-type: text/xml; charset=UTF-8
Content-length: 406
SOAPAction: "http://web.cbr.ru/GetCursOnDate"
*****************************************************但是,虽然那个特定的错误已经消失了,但是这个调用是行不通的。,因为你会带着一些问题回来,我想我可以省去一些信息交换,直接写续集。我提到了我对Python的SOAP支持在另一个场合的失望。对于这篇文章,我将在这里添加所有细节,作为对我自己的参考,并希望作为对其他用户的帮助。所以现在开始..。
调用不起作用,因为默认情况下,SOAPpy使用有序的参数进行调用。它们名为v1、v2、v3等(有关详细信息,请参阅SOAPpy下载中的MethodParameterNaming.txt文件)。您的SOAP消息将如下所示:
<SOAP-ENV:Body>
<ns1:GetCursOnDate xmlns:ns1="http://web.cbr.ru/" SOAP-ENC:root="1">
<v1>
</v1>
</ns1:GetCursOnDate>
</SOAP-ENV:Body>这个特定的web服务需要一个名为On_date的参数,而不是v1。您可以尝试通过使用命名参数来修复它:
from SOAPpy import SOAPProxy
from datetime import datetime
input = datetime.now()
namespace = "http://web.cbr.ru/"
url = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx"
soapaction = "http://web.cbr.ru/GetCursOnDate"
proxy = SOAPProxy(url, namespace = namespace, soapaction = soapaction)
proxy.config.debug = 1
proxy.GetCursOnDate(On_date = input)您的信息现在如下所示:
<SOAP-ENV:Body>
<ns1:GetCursOnDate xmlns:ns1="http://web.cbr.ru/" SOAP-ENC:root="1">
<On_date>
</On_date>
</ns1:GetCursOnDate>
</SOAP-ENV:Body>我认为日期的值丢失了,因为代理对datetime对象有问题。实际上,我并没有检查这是什么问题,因为这条消息还有另一个问题: web服务期望的是<ns1:On_date>而不是<On_date>。
这就是SOAPpy在名称空间方面存在一些问题的地方。使用原始的SOAPpy源代码,您不能更改名称空间。看起来,在Python的大多数SOAP库中,只有通过调整代码才能得到您想要的行为,这就是我所做的。我在一些处理名称空间和标记前缀的地方更改了SOAPBuilder.py文件。请参阅原始文件这里和已更改的这里。
这些更改允许我使用SOAPpy类型对消息进行更精细的控制:
from SOAPpy import SOAPProxy
from SOAPpy import Types
namespace = "http://web.cbr.ru/"
url = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx"
soapaction = "http://web.cbr.ru/GetCursOnDate"
input = Types.dateType(name = (namespace, "On_date"))
proxy = SOAPProxy(url, namespace = namespace, soapaction = soapaction)
proxy.config.debug = 1
proxy.GetCursOnDate(input)现在我得到了我想要的结果:
<SOAP-ENV:Body>
<ns1:GetCursOnDate xmlns:ns1="http://web.cbr.ru/" SOAP-ENC:root="1">
<ns1:On_date xsi:type="xsd:date">2013-11-02Z</ns1:On_date>
</ns1:GetCursOnDate>
</SOAP-ENV:Body>服务器返回上述请求的数据.
但是,即使上面的代码也可以改进。注意,我正在为一个特定的操作设置代理上的SOAPAction:GetCursOnDate。如果我想在另一个操作中使用它,我需要另一个代理,或者我需要修改这个代理。通过使用WSDL.Proxy,您可以自动从WSDL (它提供了一个从web服务的WSDL中解析方法名称、命名空间和SOAPActions的SOAPProxy包装器)获得这一点。
但是,即使这会自动处理SOAPAction,它也不会为该方法提取名称空间。所以我调整了WSDL.py文件。原始版本是这里,修改后的文件是这里。新的客户端代码现在如下所示:
from SOAPpy import WSDL
from SOAPpy import Types
# you can download this and use it locally for better performance
wsdl = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx?wsdl"
namespace = "http://web.cbr.ru/"
input = Types.dateType(name = (namespace, "On_date"))
proxy = WSDL.Proxy(wsdl, namespace = namespace)
proxy.soapproxy.config.debug = 1
proxy.GetCursOnDate(input)对于上面的示例,我使用了Python2.6.6、SOAPpy 0.12.5、fpconst0.7.2和wstools0.4.3。对于其他人,我认为YMMV取决于您正在调用的版本或特定的web服务。最后,我还想提到的是,如果你在谷歌上搜索,你会注意到大多数人推荐使用肥皂,而不是SOAPpy作为SOAP客户端,所以也许也要看看这个。祝好运!
发布于 2014-04-22 14:36:13
看起来,targetNamespace被忽略了,但是您可以为每个操作设置一个名称空间,这对soappy很好。
<operation name="createCall">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal" namespace="http://create.service/"/>
</input>
<output>
<soap:body use="literal" namespace="http://create.service/"/>
</output>
</operation>当然,您应该使用您的命名空间而不是http://create.service/。
https://stackoverflow.com/questions/19708597
复制相似问题