【发布时间】:2015-11-18 19:54:44
【问题描述】:
我在 Python SUDS 中遇到了另一个可怕的 TypeNotFound 错误(Python 2.7,suds-jurko==0.6)
这些是 XSD 的相关部分:
<xs:complexType final="extension restriction" name="requestHeader">
<xs:sequence>
<xs:element minOccurs="0" name="type" type="tns:requestType"/>
<xs:element minOccurs="0" name="userID" type="xs:string"/>
<xs:element minOccurs="0" name="sessionID" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType final="extension restriction" name="requestType">
<xs:sequence>
<xs:element name="__value" type="xs:int"/>
</xs:sequence>
</xs:complexType>
WSDL 正确导入 XSD,所以我不相信 Doctor 会提供帮助:
<wsdl:definitions
name="FooBarService"
targetNamespace="foo.bar.ns"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="foo.bar.ns"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="foo.bar.ns" schemaLocation="someschemafile.xsd"/>
<import namespace="http://jaxb.dev.java.net/array" schemaLocation="someschemafile2.xsd"/>
还有someschemafile.xsd:
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ns1="http://jaxb.dev.java.net/array"
xmlns:tns="foo.bar.ns"
attributeFormDefault="unqualified"
elementFormDefault="unqualified"
targetNamespace="foo.bar.ns">
然后我创建requestHeader 和requestType:
q = soap_client.factory.create('requestHeader')
print q
(requestHeader){
type =
(requestType){
__value = None
}
userID = None
sessionID = None
}
然后:
q.type = soap_client.factory.create('requestType')
q.type.__value = 42
q.userID = "foo"
q.sessionID = "bar"
print q
(requestHeader){
type =
(requestType){
__value = 42
}
userID = "foo"
sessionID = "bar"
}
然后我尝试调用使用requestHeader 的方法,然后我得到:
TypeNotFound(u"Type not found: '__value'",)
我也试过这个:
q = {
'type': 42,
'userID': "foo",
'sessionID': "bar"
}
但这会呈现错误的 SOAP 消息:
<header>
<type>42</type>
<userID>foo</userID>
<sessionID>bar</sessionID>
</header>
而不是
<header>
<type>
<__value>42</__value>
</type>
<userID>foo</userID>
<sessionID>bar</sessionID>
</header>
最终被服务拒绝。
很抱歉,我无法提供完整的 WSDL 和 XSD,它们受到限制。
如何使 suds 使用 __value 元素创建正确的 SOAP XML?
我正在使用 WSDL 的本地副本,所以我可以更改它,只要它产生正确的 SOAP XML。不过,我不知道要改变什么。
编辑:添加了一些清理过的回溯(在调用 SUDS 方法之前删除了一些东西)request 是 SUDS 对象,其中一个属性的类型是 requestHeader
---------------------------------------------------------------------------
FooClientClass Traceback (most recent call last)
<ipython-input-4-8ccf453fe073> in <module>()
----> 1 soap_client.service.someServiceMethod(request)
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/client.pyc in __call__(self, *args, **kwargs)
519 client = clientclass(self.client, self.method)
520 try:
--> 521 return client.invoke(args, kwargs)
522 except WebFault, e:
523 if self.faults():
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/client.pyc in invoke(self, args, kwargs)
574 timer.start()
575 binding = self.method.binding.input
--> 576 soapenv = binding.get_message(self.method, args, kwargs)
577 timer.stop()
578 metrics.log.debug("message for '%s' created: %s", self.method.name,
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/bindings/binding.pyc in get_message(self, method, args, kwargs)
107 content = self.headercontent(method)
108 header = self.header(content)
--> 109 content = self.bodycontent(method, args, kwargs)
110 body = self.body(content)
111 env = self.envelope(header, body)
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/bindings/document.pyc in bodycontent(self, method, args, kwargs)
93
94 parse_args(method.name, self.param_defs(method), args, kwargs,
---> 95 add_param, self.options().extraArgumentErrors)
96
97 return root
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/argparser.pyc in parse_args(method_name, param_defs, args, kwargs, external_param_processor, extra_parameter_errors)
81 """
82 arg_parser = _ArgParser(method_name, param_defs, external_param_processor)
---> 83 return arg_parser(args, kwargs, extra_parameter_errors)
84
85
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/argparser.pyc in __call__(self, args, kwargs, extra_parameter_errors)
106 self.__init_run(args, kwargs, extra_parameter_errors)
107 try:
--> 108 self.__process_parameters()
109 return self.__all_parameters_processed()
110 finally:
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/argparser.pyc in __process_parameters(self)
297 """Collect values for given web service operation input parameters."""
298 for pdef in self.__param_defs:
--> 299 self.__process_parameter(*pdef)
300
301 def __push_frame(self, ancestry_item):
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/argparser.pyc in __process_parameter(self, param_name, param_type, ancestry)
292 self.__stack[-1].process_parameter(param_optional, value is not None)
293 self.__external_param_processor(param_name, param_type,
--> 294 self.__in_choice_context(), value)
295
296 def __process_parameters(self):
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/bindings/document.pyc in add_param(param_name, param_type, in_choice_context, value)
84 # Construct request data for the current input parameter.
85 pdef = (param_name, param_type)
---> 86 p = self.mkparam(method, pdef, value)
87 if p is None:
88 return
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/bindings/document.pyc in mkparam(self, method, pdef, object)
128 tags.append(self.mkparam(method, pdef, item))
129 return tags
--> 130 return Binding.mkparam(self, method, pdef, object)
131
132 def param_defs(self, method):
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/bindings/binding.pyc in mkparam(self, method, pdef, object)
223 content = Content(tag=pdef[0], value=object, type=pdef[1],
224 real=pdef[1].resolve())
--> 225 return marshaller.process(content)
226
227 def mkheader(self, method, hdef, object):
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/core.pyc in process(self, content)
57 if isinstance(content.value, Property):
58 root = self.node(content)
---> 59 self.append(document, content)
60 return document.root()
61
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/core.pyc in append(self, parent, content)
70 log.debug('appending parent:\n%s\ncontent:\n%s', parent, content)
71 if self.start(content):
---> 72 self.appender.append(parent, content)
73 self.end(parent, content)
74
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
86 appender = candidate_appender
87 break
---> 88 appender.append(parent, content)
89
90
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
227 for item in object:
228 cont = Content(tag=item[0], value=item[1])
--> 229 Appender.append(self, child, cont)
230
231
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
166 @type content: L{Object}
167 """
--> 168 self.marshaller.append(parent, content)
169
170
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/core.pyc in append(self, parent, content)
70 log.debug('appending parent:\n%s\ncontent:\n%s', parent, content)
71 if self.start(content):
---> 72 self.appender.append(parent, content)
73 self.end(parent, content)
74
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
86 appender = candidate_appender
87 break
---> 88 appender.append(parent, content)
89
90
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
227 for item in object:
228 cont = Content(tag=item[0], value=item[1])
--> 229 Appender.append(self, child, cont)
230
231
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
166 @type content: L{Object}
167 """
--> 168 self.marshaller.append(parent, content)
169
170
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/core.pyc in append(self, parent, content)
70 log.debug('appending parent:\n%s\ncontent:\n%s', parent, content)
71 if self.start(content):
---> 72 self.appender.append(parent, content)
73 self.end(parent, content)
74
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
86 appender = candidate_appender
87 break
---> 88 appender.append(parent, content)
89
90
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
227 for item in object:
228 cont = Content(tag=item[0], value=item[1])
--> 229 Appender.append(self, child, cont)
230
231
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
166 @type content: L{Object}
167 """
--> 168 self.marshaller.append(parent, content)
169
170
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/core.pyc in append(self, parent, content)
69 """
70 log.debug('appending parent:\n%s\ncontent:\n%s', parent, content)
---> 71 if self.start(content):
72 self.appender.append(parent, content)
73 self.end(parent, content)
/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/literal.pyc in start(self, content)
84 content.type = self.resolver.find(name, content.value)
85 if content.type is None:
---> 86 raise TypeNotFound(content.tag)
87 else:
88 known = None
TypeNotFound(u"Type not found: '__value'",)
【问题讨论】:
-
"然后我尝试调用使用requestHeader的方法,然后我得到:"请显示您正在调用的方法。
-
您必须记住的是,以
__variable之类的双下划线开头的类变量对于python 中的类来说是私有的(它们实际上是被破坏的而不是真正私有的),这可能是你困难的原因。如果必须,我会说停止使用双下划线或使用一个下划线。通过使用重整名称的麻烦是可能的,但它真的很混乱而且不是pythonic,我会完全不鼓励它。 -
是的,我知道 Python 中的双下划线,但是……我不是请求的 SOAP API 的作者,我只是在使用它……那是企业 Java 怪物双下划线名称没有任何意义......我会看看我是否可以做一些事情来防止 Python 中的名称修改,也许这就是 SUDS 感到困惑的原因。谢谢
-
@dopstar :我不能真正展示整个方法,但它是这样的:soap_client.service.someMethod(soap_object_with_request_header)
-
类似什么?我明白,不要显示该方法是如何实现的。只需显示您如何称呼它。或者只显示完整的回溯错误消息,因为它将显示在那里而不是显示最终的错误消息。恐怕这种信息是相当有用的。除非回溯也被“限制”:)