楼主: lastwinner

[参考文档] Python 研究(Dive Into Python)

[复制链接]
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
241#
 楼主| 发表于 2006-7-19 00:08 | 只看该作者
例 12.10. 揭示方法返回值
>>> callInfo.outparams            
[<SOAPpy.wstools.WSDLTools.ParameterInfo instance at 0x00CF3AF8>]
>>> callInfo.outparams[0].name   
u'return'
>>> callInfo.outparams[0].type
(u'http://www.w3.org/2001/XMLSchema', u'float')
  与揭示函数参数的 callInfo.inparams 对应的是揭示返回值的 callInfo.outparams。它也同样是一个列表,因为通过 SOAP 调用函数时可以返回多个值,就像 Python 函数一样。
  ParameterInfo 对象包含 name 和 type。这个函数返回一个浮点值,它的名字是 return。

让我们整合一下,通过 WSDL proxy 调用一个 SOAP 网络服务。

例 12.11. 通过 WSDL proxy 调用一个 SOAP 网络服务
>>> from SOAPpy import WSDL
>>> wsdlFile = 'http://www.xmethods.net/sd/2001/TemperatureService.wsdl')
>>> server = WSDL.Proxy(wsdlFile)               
>>> server.getTemp('90210')                     
66.0
>>> server.soapproxy.config.dumpSOAPOut = 1     
>>> server.soapproxy.config.dumpSOAPIn = 1
>>> temperature = server.getTemp('90210')
*** Outgoing SOAP ******************************************************
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:getTemp xmlns:ns1="urn:xmethods-Temperature" SOAP-ENC:root="1">
<v1 xsi:type="xsd:string">90210</v1>
</ns1:getTemp>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
************************************************************************
*** Incoming SOAP ******************************************************
<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<ns1:getTempResponse xmlns:ns1="urn:xmethods-Temperature"
  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<return xsi:type="xsd:float">66.0</return>
</ns1:getTempResponse>

</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
************************************************************************

>>> temperature
66.0
  比直接调用 SOAP 服务时的设置简单,因为在 WSDL 文件中包含着调用服务所需要的服务 URL 和命名空间。创建 WSDL.Proxy 对象来下载 WSDL 文件,解析之,并设置一个用以调用实际的 SOAP 网络服务的 SOAPProxy 对象。
  WSDL.Proxy 对象一旦被创建,你可以像调用 SOAPProxy 对象一样简单地调用一个函数。这并不奇怪,WSDL.Proxy 就是一个具有自省方法的 SOAPProxy 封装套件,所以调用函数的语法也是一样的。
  你可以通过 server.soapproxy 访问 WSDL.Proxy 的 SOAPProxy。这对于打开查错模式很重要,这样一来当你通过 WSDL proxy 调用函数时,它的 SOAPProxy 将会把线路上来往的 XML 文档甩下来。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
242#
 楼主| 发表于 2006-7-19 00:09 | 只看该作者
12.7. 搜索 Google
让我们回到这章开始时你看到的那段代码,获得比当前气温更有价值和令人振奋的信息。

Google 提供了一个 SOAP API ,以便通过程序进行 Google 搜索。使用它的前提是,你注册了 Google 网络服务。

过程 12.4. 注册 Google 网络服务
访问 http://www.google.com/apis/ 并创建一个账号。 唯一的需要是提供一个 E-mail 地址。 注册之后,你将通过 E-mail 收到你的 Google API 许可证(license key)。 你需要在调用 Google 搜索函数时使用这个许可证。

还是在 http://www.google.com/apis/ 上,下载 Google 网络 APIs 开发工具包(kit)。它包含着包括 Python 在内的多种语言的样例代码,更重要的是它包含着 WSDL 文件。

解压这个开发工具包并找到 GoogleSearch.wsdl。将这个文件拷贝到你本地驱动器的一个永久地址。在本章后面位置你会用到它。

你有了开发许可证和 Google WSDL 文件之后就可以和 Google 网络服务打交道了。

例 12.12. 内省 Google 网络服务
>>> from SOAPpy import WSDL
>>> server = WSDL.Proxy('/path/to/your/GoogleSearch.wsdl')
>>> server.methods.keys()                                 
[u'doGoogleSearch', u'doGetCachedPage', u'doSpellingSuggestion']
>>> callInfo = server.methods['doGoogleSearch']
>>> for arg in callInfo.inparams:                          
...     print arg.name.ljust(15), arg.type
key             (u'http://www.w3.org/2001/XMLSchema', u'string')
q               (u'http://www.w3.org/2001/XMLSchema', u'string')
start           (u'http://www.w3.org/2001/XMLSchema', u'int')
maxResults      (u'http://www.w3.org/2001/XMLSchema', u'int')
filter          (u'http://www.w3.org/2001/XMLSchema', u'boolean')
restrict        (u'http://www.w3.org/2001/XMLSchema', u'string')
safeSearch      (u'http://www.w3.org/2001/XMLSchema', u'boolean')
lr              (u'http://www.w3.org/2001/XMLSchema', u'string')
ie              (u'http://www.w3.org/2001/XMLSchema', u'string')
oe              (u'http://www.w3.org/2001/XMLSchema', u'string')
  步入 Google 网络服务很简单:建立一个 WSDL.Proxy 对象并指向到你复制到本地的 Google WSDL 文件。
  由 WSDL 文件可知,Google 提供三个函数:doGoogleSearch, doGetCachedPage 和 doSpellingSuggestion。顾名思义,执行 Google 搜索并返回结果,获得 Google 最后一次扫描该页时获得的缓存,为基于常见拼写错误提出单词拼写建议。
  doGoogleSearch 函数需要一系列不同类型的参数。注意: WSDL 文件可以告诉你有哪些参数和他们的参数类型,但不能告诉你它们的含义和使用方法。在参数值有限定的情况下,理论上它能够告诉你参数的取值范围,但 Google 的 WSDL 没有那么细化。 WSDL.Proxy 不会变魔术,它只能给你 WSDL 文件中提供的信息。
这里简要地列出了 doGoogleSearch 函数的所有参数:
  • key —— 你注册 Google 网络服务时获得的 Google API 许可证。
  • q —— 你要搜索的词或词组。其语法与 Google 的网站表单处完全相同,你所知道的高级搜索语法和技巧这里完全适用。
  • start —— 起始的结果编号。与使用 Google 网页交互搜索时相同,这个函数每次返回10个结果。如果你需要查看 “第二” 页结果则需要将 start 设置为10。
  • maxResults —— 返回的结果个数。目前的值是10,当然如果你只对少数返回结果感兴趣或者希望节省网络带宽,也可以定义为返回更少的结果。
  • filter —— 如果设置为 True,Google 将会过滤结果中重复的页面。
  • restrict —— 这里设置 country 并跟上一个国家代码可以限定只返回特定国家的结果。例如: countryUK 用于在英国搜索页面。你也可以设定 linux, mac 或者 bsd 以便搜索 Google 定义的技术站点组,或者设为 unclesam 来搜索美国政府站点。
  • safeSearch —— 如果设置为 True, Google 将会过滤掉色情站点。
  • lr (“语言限制”) —— 这里设置语言限定值返回特定语言的站点。
  • ie and oe (“输入编码” 和 “输出编码”) —— 不赞成使用,都应该是 utf-8。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
243#
 楼主| 发表于 2006-7-19 00:09 | 只看该作者
例 12.13. 搜索 Google
>>> from SOAPpy import WSDL
>>> server = WSDL.Proxy('/path/to/your/GoogleSearch.wsdl')
>>> key = 'YOUR_GOOGLE_API_KEY'
>>> results = server.doGoogleSearch(key, 'mark', 0, 10, False, "",
...     False, "", "utf-8", "utf-8"            
>>> len(results.resultElements)                  
10
>>> results.resultElements[0].URL               
'http://diveintomark.org/'
>>> results.resultElements[0].title
'dive into <b>mark</b>'
  在设置好 WSDL.Proxy 对象之后,你可以使用十个参数来调用 server.doGoogleSearch。 记住在要使用你注册 Google 网络服务时授权给你自己的 Google API 许可证。
  有很多的返回信息,但我们还是先来看一下实际的返回结果。它们被存储于 results.resultElements 之中,你可以像使用普通的 Python 列表那样来调用它。
  resultElements 中的每个元素都是一个包含 URL, title, snippet 以及其他属性的对象。基于这一点,你可以使用诸如 dir(results.resultElements[0]) 的普通 Python 自省技术来查看有效属性,或者通过 WSDL proxy 对象查看函数的 outparams。 不同的方法能带给你相同的结果。

results 对象中所加载的不仅仅是实际的搜索结果。 它也含有搜索行为自身的信息,比如耗时和总结果数等(尽管只返回了10条结果)。 Google 网页界面中显示了这些信息,通过程序你也同样能获得它们。

例 12.14. 从Google获得次要信息
>>> results.searchTime                     
0.224919
>>> results.estimatedTotalResultsCount     
29800000
>>> results.directoryCategories            
[<SOAPpy.Types.structType item at 14367400>:
{'fullViewableName':
  'Top/Arts/Literature/World_Literature/American/19th_Century/Twain,_Mark',
  'specialEncoding': ''}]
>>> results.directoryCategories[0].fullViewableName
'Top/Arts/Literature/World_Literature/American/19th_Century/Twain,_Mark'
  这个搜索耗时 0.224919 秒。这不包括用于发送和接收 SOAP XML 文档的时间,仅仅是 Google 在接到搜索请求后执行搜索所花费的时间。
  总共有接近30,000,000个结果信息,你可以通过以 10 递增地改变 start 参数来重复调用 server.doGoogleSearch 。
  对于有些请求,Google 还返回一个 Google Directory 中的类别列表。你可以用这些 URLs 到 http://directory.google.com/ 建立到 directory category 页面的链接。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
244#
 楼主| 发表于 2006-7-19 00:09 | 只看该作者
12.8.  SOAP 网络服务故障排除
是的,SOAP 网络服务的世界中也不总是欢乐和阳光。 有时候也会有故障。

正如你在本章中看到的,SOAP 牵扯了很多层面。 需要 HTTP 层,SOAP 需要向 HTTP 服务器发送 XML 文档并接收返回的 XML 文档。这样一来,你在 第 11 章 HTTP Web 服务 学到的差错技术在这里都有了用武之地。你可以 import httplib 并设置 httplib.HTTPConnection.debuglevel = 1 来查看潜在的 HTTP 传输。

在 HTTP 层之上,还有几个可能发生问题的地方。 SOAPpy 隐藏 SOAP 语法的本领令你惊叹不已,但也意味着在发生问题时更难确定问题所在。

下面的这些例子是我在使用 SOAP 网络服务时犯过的一些常见错误以及所产生的错误信息。

例 12.15. 以错误的设置调用 Proxy 方法
>>> from SOAPpy import SOAPProxy
>>> url = 'http://services.xmethods.net:80/soap/servlet/rpcrouter'
>>> server = SOAPProxy(url)                                       
>>> server.getTemp('27502')                                       
<Fault SOAP-ENV:Server.BadTargetObjectURI:
Unable to determine object id from call: is the method element namespaced?>
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "c:\python23\Lib\site-packages\SOAPpy\Client.py", line 453, in __call__
    return self.__r_call(*args, **kw)
  File "c:\python23\Lib\site-packages\SOAPpy\Client.py", line 475, in __r_call
    self.__hd, self.__ma)
  File "c:\python23\Lib\site-packages\SOAPpy\Client.py", line 389, in __call
    raise p
SOAPpy.Types.faultType: <Fault SOAP-ENV:Server.BadTargetObjectURI:
Unable to determine object id from call: is the method element namespaced?>
  你看出错误了吗?你手工地创建了一个 SOAPProxy ,你正确地制定了服务 URL,但是你没有指定命名空间。 由于多个服务可能被路由到相同的服务 URL,命名空间是确定你所调用的服务和方法的重要内容。
  服务器返回的是一个 SOAP 错误,SOAPpy 溢出了SOAPpy.Types.faultType 这个 Python 异常。 从任何 SOAP 服务器返回的错误都是 SOAP 错误,因此你可以轻易地捕获这个异常。就此出而言,我们能从 SOAP 错误信息中看出端倪:由于源 SOAPProxy 对象没有设置服务命名空间,因此方法元素也就没有了命名空间。

错误配置 SOAP 服务的基本元素是 WSDL 问题解决的着眼点。 WSDL 文件包含服务 URL 和命名空间,所以你应该不会在这里犯错。但是,还有其他可能出错的地方。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
245#
 楼主| 发表于 2006-7-19 00:09 | 只看该作者
例 12.16. 以错误参数调用方法
>>> wsdlFile = 'http://www.xmethods.net/sd/2001/TemperatureService.wsdl'
>>> server = WSDL.Proxy(wsdlFile)
>>> temperature = server.getTemp(27502)                                
<Fault SOAP-ENV:Server: Exception while handling service request:
services.temperature.TempService.getTemp(int) -- no signature match>   
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "c:\python23\Lib\site-packages\SOAPpy\Client.py", line 453, in __call__
    return self.__r_call(*args, **kw)
  File "c:\python23\Lib\site-packages\SOAPpy\Client.py", line 475, in __r_call
    self.__hd, self.__ma)
  File "c:\python23\Lib\site-packages\SOAPpy\Client.py", line 389, in __call
    raise p
SOAPpy.Types.faultType: <Fault SOAP-ENV:Server: Exception while handling service request:
services.temperature.TempService.getTemp(int) -- no signature match>
  你看出错误了吗? 这是一个不易察觉的错误:你在使用整数而不是字符串来调用 server.getTemp 。自省 WSDL 文件不难发现,getTemp() 这个 SOAP 函数接受一个参数 zipcode,这是一个字符串参数。 WSDL.Proxy 不 会为你强制数据类型;你需要根据服务器需要的数据类型传递数据。
  又是这样,服务器传回一个 SOAP 错误,你能从 SOAP 错误信息中看出端倪:你在使用整数类型的参数调用 getTemp 函数,但却没有一个以此命名的函数接收整数参数。理论上讲, SOAP 允许你重载 overload 函数,也就是可以在同一个 SOAP 服务中存在同名函数,并且参数个数也相同,但是参数的数据类型不同。这就是数据类型必须匹配的原因,也说明了为什么 WSDL.Proxy 不强制地为你改变数据类型。如果真的强制改变了数据类型,发生这样的错误时,调用的可能是另外一个不相干的函数。看来产生这样的错误是件幸运的事。对于数据类型多加注意会让事情简单很多,一旦搞错了数据类型便立刻会发生错误。

Python 所期待的返回值个数与远程函数的实际返回值个数不同是另一种可能的错误。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
246#
 楼主| 发表于 2006-7-19 00:10 | 只看该作者
例 12.17. 调用时方法所期待的返回值个数错误
>>> wsdlFile = 'http://www.xmethods.net/sd/2001/TemperatureService.wsdl'
>>> server = WSDL.Proxy(wsdlFile)
>>> (city, temperature) = server.getTemp(27502)  
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unpack non-sequence
  你看出错误了吗? server.getTemp 只返回一个浮点值,但你写的代码却期待着获得两个值,并把它们赋值给不同的两个变量。注意这不是一个 SOAP 错误。就远程服务器而言没有发生任何错误。错误发生在完成 SOAP 交割之后。 WSDL.Proxy 返回一个浮点数,你本地的 Python 解释器试图将这个浮点数分成两个变量。由于函数只返回了一个值,你在试图分割它时所获得的是一个 Python 异常,而不是 SOAP 错误。

那么 Google 网络服务方面又如何呢?最常见的错误是我曾经犯过的忘记正确设置应用许可证错误。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
247#
 楼主| 发表于 2006-7-19 00:10 | 只看该作者
例 12.18. 调用方法返回一个应用指定错误
>>> from SOAPpy import WSDL
>>> server = WSDL.Proxy(r'/path/to/local/GoogleSearch.wsdl')
>>> results = server.doGoogleSearch('foo', 'mark', 0, 10, False, "",
...     False, "", "utf-8", "utf-8"
<Fault SOAP-ENV:Server:                                             
Exception from service object: Invalid authorization key: foo:
<SOAPpy.Types.structType detail at 14164616>:
{'stackTrace':
  'com.google.soap.search.GoogleSearchFault: Invalid authorization key: foo
   at com.google.soap.search.QueryLimits.lookUpAndLoadFromINSIfNeedBe(
     QueryLimits.java:220)
   at com.google.soap.search.QueryLimits.validateKey(QueryLimits.java:127)
   at com.google.soap.search.GoogleSearchService.doPublicMethodChecks(
     GoogleSearchService.java:825)
   at com.google.soap.search.GoogleSearchService.doGoogleSearch(
     GoogleSearchService.java:121)
   at sun.reflect.GeneratedMethodAccessor13.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at java.lang.reflect.Method.invoke(Unknown Source)
   at org.apache.soap.server.RPCRouter.invoke(RPCRouter.java:146)
   at org.apache.soap.providers.RPCJavaProvider.invoke(
     RPCJavaProvider.java:129)
   at org.apache.soap.server.http.RPCRouterServlet.doPost(
     RPCRouterServlet.java:288)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
   at com.google.gse.HttpConnection.runServlet(HttpConnection.java:237)
   at com.google.gse.HttpConnection.run(HttpConnection.java:195)
   at com.google.gse.DispatchQueue$WorkerThread.run(DispatchQueue.java:201)
Caused by: com.google.soap.search.UserKeyInvalidException: Key was of wrong size.
   at com.google.soap.search.UserKey.<init>(UserKey.java:59)
   at com.google.soap.search.QueryLimits.lookUpAndLoadFromINSIfNeedBe(
     QueryLimits.java:217)
   ... 14 more
'}>
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "c:\python23\Lib\site-packages\SOAPpy\Client.py", line 453, in __call__
    return self.__r_call(*args, **kw)
  File "c:\python23\Lib\site-packages\SOAPpy\Client.py", line 475, in __r_call
    self.__hd, self.__ma)
  File "c:\python23\Lib\site-packages\SOAPpy\Client.py", line 389, in __call
    raise p
SOAPpy.Types.faultType: <Fault SOAP-ENV:Server: Exception from service object:
Invalid authorization key: foo:
<SOAPpy.Types.structType detail at 14164616>:
{'stackTrace':
  'com.google.soap.search.GoogleSearchFault: Invalid authorization key: foo
   at com.google.soap.search.QueryLimits.lookUpAndLoadFromINSIfNeedBe(
     QueryLimits.java:220)
   at com.google.soap.search.QueryLimits.validateKey(QueryLimits.java:127)
   at com.google.soap.search.GoogleSearchService.doPublicMethodChecks(
     GoogleSearchService.java:825)
   at com.google.soap.search.GoogleSearchService.doGoogleSearch(
     GoogleSearchService.java:121)
   at sun.reflect.GeneratedMethodAccessor13.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at java.lang.reflect.Method.invoke(Unknown Source)
   at org.apache.soap.server.RPCRouter.invoke(RPCRouter.java:146)
   at org.apache.soap.providers.RPCJavaProvider.invoke(
     RPCJavaProvider.java:129)
   at org.apache.soap.server.http.RPCRouterServlet.doPost(
     RPCRouterServlet.java:288)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
   at com.google.gse.HttpConnection.runServlet(HttpConnection.java:237)
   at com.google.gse.HttpConnection.run(HttpConnection.java:195)
   at com.google.gse.DispatchQueue$WorkerThread.run(DispatchQueue.java:201)
Caused by: com.google.soap.search.UserKeyInvalidException: Key was of wrong size.
   at com.google.soap.search.UserKey.<init>(UserKey.java:59)
   at com.google.soap.search.QueryLimits.lookUpAndLoadFromINSIfNeedBe(
     QueryLimits.java:217)
   ... 14 more
'}>
  你看出错误了吗? 调用的语法,参数个数以及数据类型都没有错误。 问题在于应用指定:第一个参数应该是我的应用许可证,但 foo 不是一个有效的 Google 许可证。
  Google 服务器返回的是一个 SOAP 错误和一大串特别长的错误信息,其中包含了完整的 Java 堆栈跟踪。 记住 所有 的 SOAP 错误都被标示为 SOAP 错误:设置错误,函数参数错误以及应用指定错误等等。在其中埋藏的至关重要信息确是:非有效授权许可证:foo (Invalid authorization key: foo)。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
248#
 楼主| 发表于 2006-7-19 00:10 | 只看该作者
进一步阅读

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
249#
 楼主| 发表于 2006-7-19 00:10 | 只看该作者
12.9. 小结
SOAP 网络服务是很复杂的,雄心勃勃的它试图涵盖网络服务的很多不同应用。这一章我们接触了它的一个简单应用。
在开始下一章的学习之前,确保你能自如地做如下工作:
  • 连接到 SOAP 服务器并调用远程方法
  • 通过 WSDL 文件自省远程方法
  • 有效排除 SOAP 调用中的错误
  • 排除常见的 SOAP 相关错误

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
250#
 楼主| 发表于 2006-7-19 00:11 | 只看该作者
第 13 章 单元测试
13.1. 罗马数字程序介绍 II
13.2. 深入
13.3. 介绍 romantest.py
13.4. 正面测试(Testing for success)
13.5. 负面测试(Testing for failure)
13.6. 完备性检测(Testing for sanity)
13.1. 罗马数字程序介绍 II
在前面的章节中,你迅速“深入”并试图以最快的速度理解了这个程序。 " 既然你已对 Python 有了一定的了解,那么接下来将回顾这个程序并从其代码被开发之前入手。

在接下来的几章中,你将会编写,调试和优化一系列工具函数来进行罗马数字和阿拉伯数字之间的转换。你已从第 7.3 节 “个案研究:罗马字母”中获知构造和验证罗马数字的机制,现在我们要做的事是退后一步去思考如何将这些机制扩展到一个双向转换的工具。

罗马数字的规则有如下一些有趣的特点:

一个特定数字以罗马数字表示时只有单一方式。
反之亦然:一个有效的罗马数字表示的数也只对应一个阿拉伯数字表示。(也就是说转换成阿拉伯数字表示只有一种方法).
我们研究的是 1 和 3999 之间的数字的罗马数字表示。(罗马数字有很多方法用以记录更大的数,例如在数字上加线表示1000倍的数,但你不必去理会这些。就本章而言,我们姑且把罗马数字限定在 1 到 3999 之间)。
罗马数字无法表示 0 (令人诧异,古罗马竟然没有 0 这个数字的概念。数字是为数数服务的,没有怎么数呢?)
罗马数字不能表示负数。
罗马数字无法表示分数和非整数。
基于如上所述,你将如何构造罗马数字转换函数呢?


roman.py 功能需求
  • toRoman 应该返回所有 1 到 3999 的罗马数字表示。
  • toRoman 在遇到 1 到 3999 之外的数字时应该失败。
  • toRoman 在遇到非整数时应该失败。
  • fromRoman 应该能将给定的有效罗马数字表示转换为阿拉伯数字表示。
  • fromRoman 在遇到无效罗马数字表示时应该失败。
  • 将一个数转换为罗马数字表示,再转换回阿拉伯数字表示后应该和最初的数相同。因此,fromRoman(toRoman(n)) == n 对于 1..3999 之间所有 n 都适用。
  • toRoman 返回的罗马数字应该使用大写字母。
  • fromRoman 应该只接受大写罗马数字(也就是说给定小写字母进行转换时应该失败)。

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表