我正在尝试通过在Python 2.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)
但是我得到一个错误:
错误肥皂:客户端:服务器无法识别HTTP标头SOAPAction:GetCursOnDate的值。
为什么会出现此错误?
默认情况下,SOAPpy使用方法名称作为HTTPSOAPAction
标头的值。如果运行以下代码,您将在调试输出中看到该值:
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
请参见MethodParameterNaming.txt
SOAPpy下载中的文件)。您的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
not 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
。如果要与其他操作一起使用,则需要另一个代理,或者需要修改它。通过使用a,WSDL.Proxy
您可以从WSDL自动获得它(它提供了一个SOAPProxy
包装程序,该包装程序可以SOAPAction
从Web服务的WSDL中解析方法名称,名称空间和s)。
但是,即使这是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)
对于上面的示例,我使用了Python 2.6.6,SOAPpy 0.12.5,fpconst 0.7.2和wstools 0.4.3。对于其他人,我认为YMMV取决于您正在调用的版本或特定的Web服务。最后,我还想提及一下,如果您在Google上进行搜索,您会发现大多数人都建议使用SUDS而不是SOAPpy作为SOAP客户端,所以也许也可以看看。祝好运!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句