Changeset 832

Show
Ignore:
Timestamp:
Tue Mar 7 06:30:50 2006
Author:
osmond
Message:

update

Files:

Legend:

Unmodified
Added
Removed
Modified
  • zh-translations/branches/diveintopython-zh-5.4/zh-cn/xml/soap.xml

    r201 r832  
    2 2 <chapter id="soap">  
    3 3 <?dbhtml filename="soap_web_services/index.html"?>  
    4   <title>&soap; Web Services</title>  
    5   <titleabbrev id="soap.numberonly">Chapter 12</titleabbrev>  
      4 <title>&soap; Web 服务</title>  
      5 <titleabbrev id="soap.numberonly">第 12 章</titleabbrev>  
    6 6 <abstract>  
    7   <para><xref linkend="oa" endterm="oa.numberonly"/> focused on document-oriented web services over HTTP.  The <quote>input parameter</quote> was the &url;, and the <quote>return value</quote> was an actual XML document which it was your responsibility to parse.</para>  
    8   <para>This chapter will focus on &soap; web services, which take a more structured approach.  Rather than dealing with HTTP requests and XML documents directly, &soap; allows you to simulate calling functions that return native data types.  As you will see, the illusion is almost perfect; you can <quote>call</quote> a function through a &soap; library, with the standard &python; calling syntax, and the function appears to return &python; objects and values.  But under the covers, the &soap; library has actually performed a complex transaction involving multiple XML documents and a remote server.</para>  
    9   <para>&soap; is a complex specification, and it is somewhat misleading to say that &soap; is all about calling remote functions.  Some people would pipe up to add that &soap; allows for one-way asynchronous message passing, and document-oriented web services.  And those people would be correct; &soap; can be used that way, and in many different ways.  But this chapter will focus on so-called <quote>RPC-style</quote> &soap; -- calling a remote function and getting results back.</para>  
      7 <para><xref linkend="oa" endterm="oa.numberonly"/> 关注 HTTP 上面向文档的web 服务。 <quote>输入参数</quote> 是 &url;, <quote>返回值</quote> 是需要你来解析的一个实际的 XML 文档</para>  
      8 <para>本章将更加结构化地关注 &soap; web 服务。 &soap;允许你模拟返回自有数据类型的函数调用,而不仅仅是直接地矗立 HTTP 请求和XML文档. 正像你将要看到的,这个描述恰如其分;你可以使用标准&python;调用语法通过&soap;库去调用一个函数,这个函数也自然会返回 &python; 对象和值. 但解开这层面纱, &soap; 库实际上扮演了一个多XML文档和远程服务器参与的复杂处理过程。</para>  
      9 <para>&soap; 的贴切定义很复杂,不要误认为 &soap; 就是用于调用远程函数。有些人觉得应该补充上: &soap; 还允许单向异步的信息通过,并且是面向文档的Web服务。 这样想法的人是正确的,&soap; 的确是这样,但却不止于此。但这一章的重点在于所谓的 <quote>RPC-style</quote> &soap; -- 调用远程函数获得返回结果。</para>  
    10 10 </abstract>  
    11 11 <section id="soap.divein">  
    12   <title>Diving In</title>  
      12 <title>概览</title>  
    12 12 <abstract>  
    13 13 <title/>  
    14   <para>You use Google, right?  It's a popular search engine.  Have you ever wished you could programmatically access Google search results?  Now you can.  Here is a program to search Google from &python;.</para>  
      14 <para>你用 Google, 对吧?  它是一个很流行的搜索引擎。  你是否曾经希望能以程序化的方式访问 Google 的搜索结果呢?  现在你能做到了。  下面是一个用 &python; 搜索 Google 的程序。</para>  
    14 14 </abstract>  
    15 15 <example>  
     
    19 19 <programlisting>from SOAPpy import WSDL  
    20 20  
    21   # you'll need to configure these two values;  
    22   # see http://www.google.com/apis/  
      21 # 你应该理解下面这两个值;  
      22 # 察看 http://www.google.com/apis/  
    23 23 WSDLFILE = '/path/to/copy/of/GoogleSearch.wsdl'  
    24 24 APIKEY = 'YOUR_GOOGLE_API_KEY'  
     
    42 42         print</programlisting>  
    43 43 </example>  
    44   <para>You can import this as a module and use it from a larger program, or you can run the script from the command line.  On the command line, you give the search query as a command-line argument, and it prints out the URL, title, and description of the top five Google search results.</para>  
    45   <para>Here is the sample output for a search for the word <quote>python</quote>.</para>  
      44 <para>你可以在较大的程序中以模块导入并使用它, 也可以在命令行上运行这个脚本。在命令行上, 需要把查询字符串作为命令行参数使用, 之后就会打印出最前面的五个  Google 查询结果,包括: URL, 标题和描述信息。</para>  
      45 <para>下面是以 <quote>python</quote> 作为命令行参数的查询结果。</para>  
    46 46 <example>  
    47   <title>Sample Usage of <filename>search.py</filename></title>  
      47 <title><filename>search.py</filename> 的使用样例</title>  
    47 47 <screen>  
    48 48 <prompt>C:\diveintopython\common\py></prompt> <userinput>python search.py "python"</userinput>  
     
    78 78 </example>  
    79 79 <itemizedlist role="furtherreading">  
    80   <title>Further Reading on &soap;</title>  
    81   <listitem><para><ulink url="http://www.xmethods.net/"/> is a repository of public access &soap; web services.</para></listitem>  
    82   <listitem><para>The <ulink url="http://www.w3.org/TR/soap/">&soap; specification</ulink> is surprisingly readable, if you like that sort of thing.</para></listitem>  
      80 <title>进一步阅读</title>  
      81 <listitem><para><ulink url="http://www.xmethods.net/"/> 是一个访问 &soap; web 服务的公共知识库。</para></listitem>  
      82 <listitem><para><ulink url="http://www.w3.org/TR/soap/">&soap; 说明书</ulink> 对于 &soap; 相关的问题讨论非常易读。</para></listitem>  
    83 83 </itemizedlist>  
    84 84 </section>  
    85 85 <section id="soap.install">  
    86 86 <?dbhtml filename="soap_web_services/install.html"?>  
    87   <title>Installing the SOAP Libraries</title>  
      87 <title>安装 SOAP 库</title>  
    87 87 <abstract>  
    88 88 <title/>  
    89   <para>Unlike the other code in this book, this chapter relies on libraries that do not come pre-installed with &python;.</para>  
      89 <para>与本书中的其他代码不同, 本章依赖的库不是 &python; 预安装的。</para>  
    89 89 </abstract>  
    90   <para>Before you can dive into &soap; web services, you'll need to install three libraries: &pyxml;, &fpconst;, and &soappy;.</para>  
      90 <para>在深入学习 &soap; web 服务之前, 你需要安装三个库: &pyxml;, &fpconst; 和 &soappy;。</para>  
    90 90 <section>  
    91   <title>Installing &pyxml;</title>  
    92   <para>The first library you need is &pyxml;, an advanced set of &xml; libraries that provide more functionality than the built-in &xml; libraries we studied in <xref linkend="kgp" endterm="kgp.numberonly"/>.</para>  
      91 <title>安装 &pyxml;</title>  
      92 <para>你所要用到的第一个库是 &pyxml;,是 &xml;库的一个高级组件,这个库提供了比我们在 <xref linkend="kgp" endterm="kgp.numberonly"/> 学习的 &xml; 内建库提供更多的功能。</para>  
    93 93 <procedure>  
    94 94 <title/>  
    95   <para>Here is the procedure for installing &pyxml;:</para>  
    96   <step><para>Go to <ulink url="&url_pyxml;"/>, click Downloads, and download the latest version for your operating system.</para></step>  
    97   <step><para>If you are using &windows;, there are several choices.  Make sure to download the version of &pyxml; that matches the version of &python; you are using.</para></step>  
    98   <step><para>Double-click the installer.  If you download &pyxml; 0.8.3 for &windows; and &python; 2.3, the installer program will be <filename>PyXML-0.8.3.win32-py2.3.exe</filename>.</para></step>  
    99   <step><para>Step through the installer program.</para></step>  
    100   <step><para>After the installation is complete, close the installer.  There will not be any visible indication of success (no programs installed on the Start Menu or shortcuts installed on the desktop).  &pyxml; is simply a collection of &xml; libraries used by other programs.</para></step>  
      95 <para>下面是安装 &pyxml; 的步骤:</para>  
      96 <step><para>访问 <ulink url="&url_pyxml;"/>, 点击 Downloads, 下载适合你所使用操作系统的最新版本。</para></step>  
      97 <step><para>如果你所使用的是 &windows;,那么你有多个选择。一定要确保你所下载的 &pyxml; 和你所使用的 &python; 版本匹配。</para></step>  
      98 <step><para>双击安装程序。如果你下载的是为 &windows; 提供的 &pyxml; 0.8.3 ,并且你所使用的是 &python; 2.3,这个安装程序应该是 <filename>PyXML-0.8.3.win32-py2.3.exe</filename>.</para></step>  
      99 <step><para>深入安装过程</para></step>  
      100 <step><para>安装完成后,关闭安装程序,没有任何安装成功的昭示(并没有在开始菜单、快捷栏或桌面出现图标)。因为  &pyxml; 仅仅是被其他程序调用的 &xml; 的库集合。</para></step>  
    101 101 </procedure>  
    102   <para>To verify that you installed &pyxml; correctly, run your &python; &ide; and check the version of the &xml; libraries you have installed, as shown here.</para>  
      102 <para>希望检验 &pyxml; 安装的是否正确,可以运行 &python; &ide; ,如下面看到的可以看到 &xml; 库的安装版本。</para>  
    102 102 <example>  
    103   <title>Verifying &pyxml; Installation</title>  
      103 <title>检验 &pyxml; 安装</title>  
    103 103 <screen>  
    104 104 &prompt;<userinput>import xml</userinput>  
     
    111 111 <computeroutput>'0.8.3'</computeroutput>  
    112 112 </screen>  
    113   <para>This version number should match the version number of the &pyxml; installer program you downloaded and ran.</para>  
      113 <para>这个安装版本号应该和你所下载并安装的 &pyxml; 安装程序版本号一致。</para>  
    113 113 </example>  
    114 114 </section>  
    115 115 <section>  
    116   <title>Installing &fpconst;</title>  
    117   <para>The second library you need is &fpconst;, a set of constants and functions for working with IEEE754 double-precision special values.  This provides support for the special values Not-a-Number (NaN), Positive Infinity (Inf), and Negative Infinity (-Inf), which are part of the &soap; datatype specification.</para>  
      116 <title>安装 &fpconst;</title>  
      117 <para>你所需要安装的第二个库是 &fpconst;,使一系列支持 IEEE754 double-precision 特殊值得常量和函数。提供了对 Not-a-Number (NaN), Positive Infinity (Inf), and Negative Infinity (-Inf)等特殊值得支持,这是 &soap; 数据类型规范的组成部分。</para>  
    118 118 <procedure>  
    119 119 <title/>  
    120   <para>Here is the procedure for installing &fpconst;:</para>  
    121   <step><para>Download the latest version of &fpconst; from <ulink url="&url_fpconst;"/>.</para></step>  
    122   <step><para>There are two downloads available, one in <filename>.tar.gz</filename> format, the other in <filename>.zip</filename> format.  If you are using &windows;, download the <filename>.zip</filename> file; otherwise, download the <filename>.tar.gz</filename> file.</para></step>  
    123   <step><para>Decompress the downloaded file.  On &windows; XP, you can right-click on the file and choose Extract All; on earlier versions of &windows;, you will need a third-party program such as WinZip.  On &macosx;, you can double-click the compressed file to decompress it with Stuffit Expander.</para></step>  
    124   <step><para>Open a command prompt and navigate to the directory where you decompressed the &fpconst; files.</para></step>  
    125   <step><para>Type <userinput>python setup.py install</userinput> to run the installation program.</para></step>  
      120 <para>下面是 &fpconst; 的安装过程</para>  
      121 <step><para>从 <ulink url="&url_fpconst;"/> 下载 &fpconst; 的最新版本。</para></step>  
      122 <step><para>提供了两种格式的下载: <filename>.tar.gz</filename> 和 <filename>.zip</filename>。如果你使用的是 &windows; 操作系统,下载 <filename>.zip</filename> 文件;其他情况下应该下载 <filename>.tar.gz</filename> 文件。</para></step>  
      123 <step><para>对这个文件进行解压缩。在D &windows; XP 上你可以鼠标右键单击这个文件并选择“解压文件”;在较早的 &windows; 版本上则需要WinZip之类的第三方解压程序。在 &macosx;上,可以右键单击压缩文件进行解压。</para></step>  
      124 <step><para>打开命令提示符窗口并定位到解压目录。</para></step>  
      125 <step><para>键入 <userinput>python setup.py install</userinput> 运行安装程序。</para></step>  
    126 126 </procedure>  
    127   <para>To verify that you installed &fpconst; correctly, run your &python; &ide; and check the version number.</para>  
      127 <para>希望检验 &fpconst; 安装的是否正确, 运行 &python; &ide; 并查看版本号.</para>  
    127 127 <example>  
    128   <title>Verifying &fpconst; Installation</title>  
      128 <title>检验 &fpconst; 安装</title>  
    128 128 <screen>  
    129 129 &prompt;<userinput>import fpconst</userinput>  
     
    134 134 <computeroutput>'0.6.0'</computeroutput>  
    135 135 </screen>  
    136   <para>This version number should match the version number of the &fpconst; archive you downloaded and installed.</para>  
      136 <para>这个安装版本号应该和你所下载并用于安装的 &fpconst; 压缩包版本号一致。</para>  
    136 136 </example>  
    137 137 </section>  
    138 138 <section>  
    139   <title>Installing &soappy;</title>  
    140   <para>The third and final requirement is the &soap; library itself: &soappy;.</para>  
      139 <title>安装 &soappy;</title>  
      140 <para>第三个,也是最后一个需要安装的库是 &soap; 库本身: &soappy;.</para>  
    141 141 <procedure>  
    142 142 <title/>  
    143   <para>Here is the procedure for installing &soappy;:</para>  
    144   <step><para>Go to <ulink url="&url_soappy;"/> and select Latest Official Release under the &soappy; section.</para></step>  
    145   <step><para>There are two downloads available.  If you are using &windows;, download the <filename>.zip</filename> file; otherwise, download the <filename>.tar.gz</filename> file.</para></step>  
    146   <step><para>Decompress the downloaded file, just as you did with &fpconst;.</para></step>  
    147   <step><para>Open a command prompt and navigate to the directory where you decompressed the &soappy; files.</para></step>  
    148   <step><para>Type <userinput>python setup.py install</userinput> to run the installation program.</para></step>  
      143 <para>下面是安装 &soappy;的过程</para>  
      144 <step><para>访问 <ulink url="&url_soappy;"/> 并选择 &soappy; 部分中最新的官方发布</para></step>  
      145 <step><para>提供了两种格式的下载。如果你使用的是 &windows;,那么下载 <filename>.zip</filename> 文件;其他情况则下载 <filename>.tar.gz</filename> 文件。</para></step>  
      146 <step><para>和安装 &fpconst; 时一样先解压下载的文件.</para></step>  
      147 <step><para>打开名利提示符窗口并定位到解压 &soappy; 文件的目录.</para></step>  
      148 <step><para>键入 <userinput>python setup.py install</userinput> 运行安装程序</para></step>  
    149 149 </procedure>  
    150   <para>To verify that you installed &soappy; correctly, run your &python; &ide; and check the version number.</para>  
      150 <para>希望检验 &soappy; 安装的是否正确, 运行 &python; &ide; 并查看版本号.</para>  
    150 150 <example>  
    151   <title>Verifying &soappy; Installation</title>  
      151 <title>检验 &soappy; 安装</title>  
    151 151 <screen>  
    152 152 &prompt;<userinput>import SOAPpy</userinput>  
     
    157 157 <computeroutput>'0.11.4'</computeroutput>  
    158 158 </screen>  
    159   <para>This version number should match the version number of the &soappy; archive you downloaded and installed.</para>  
      159 <para>这个安装版本号应该和你所下载并用于安装的 &soappy; 压缩包版本号一致。</para>  
    159 159 </example>  
    160 160 </section>  
     
    163 163 <section id="soap.firststeps">  
    164 164 <?dbhtml filename="soap_web_services/first_steps.html"?>  
    165   <title>First Steps with &soap;</title>  
      165 <title>步入 &soap;</title>  
    165 165 <abstract>  
    166 166 <title/>  
    167   <para>The heart of &soap; is the ability to call remote functions.  There are a number of public access &soap; servers that provide simple functions for demonstration purposes.</para>  
      167 <para>调用远程函数是 &soap; 的核心功能。有很多提供公开 &soap; 访问的服务器提供用于展示的简单功能。</para>  
    167 167 </abstract>  
    168   <para>The most popular public access &soap; server is <ulink url="http://www.xmethods.net/"/>.  This example uses a demonstration function that takes a United States zip code and returns the current temperature in that region.</para>  
      168 <para>最受欢迎的 &soap; 公开访问服务器是 <ulink url="http://www.xmethods.net/"/>。这个例子使用了一个展示函数,可以根据美国邮政编码返回当地气温。</para>  
    168 168 <example>  
    169   <title>Getting the Current Temperature</title>  
      169 <title>获得现在的气温</title>  
    169 169 <screen>  
    170 170 &prompt;<userinput>from SOAPpy import SOAPProxy</userinput>            <co id="soap.firststeps.1.1"/>  
     
    181 181 <calloutlist>  
    182 182 <callout arearefs="soap.firststeps.1.1">  
    183   <para>You access the remote &soap; server through a proxy class, <classname>SOAPProxy</classname>.  The proxy handles all the internals of &soap; for you, including creating the XML request document out of the function name and argument list, sending the request over HTTP to the remote &soap; server, parsing the XML response document, and creating native &python; values to return.  You'll see what these XML documents look like in the next section.</para>  
      183 <para>你通过<classname>SOAPProxy</classname>这个 proxy 类访问远程 &soap; 服务器。这个 proxy 处理了所有的 &soap; 内部事务,其中包括:根据函数名和参数列表创建XML请求文档并将这个请求文档通过HTTP发送到远程 &soap; 服务器,解析XML返回文档并创建 &python; 原始返回值。在下一节中你将看到这个XML文档。</para>  
    183 183 </callout>  
    184 184 <callout arearefs="soap.firststeps.1.2">  
    185   <para>Every &soap; service has a &url; which handles all the requests.  The same &url; is used for all function calls.  This particular service only has a single function, but later in this chapter you'll see examples of the Google &api;, which has several functions.  The service &url; is shared by all functions.</para>  
    186   <para>Each &soap; service also has a namespace, which is defined by the server and is completely arbitrary.  It's simply part of the configuration required to call &soap; methods.  It allows the server to share a single service &url; and route requests between several unrelated services.  It's like dividing &python; modules into <link linkend="kgp.packages">packages</link>.</para>  
      185 <para>每个 &soap; 服务都有一个 &url; 用以处理所有请求。 相同的 &url; 可以用于所有的函数请求。每个特定服务则只有一个函数。但稍后你将看到的 Google &api; 却有多个函数。这个服务的 &url; 提供给所有函数分享。</para>  
      186 <para>每个 &soap; 服务都有一个命名空间(namespace),这个命名空间是由服务器任意命名的。这不过是为了调用 &soap; 方法而设置的。它使得服务器为多个不相关的服务提供服务 &url; 共享成为可能。这与 &python; 中模块到<link linkend="kgp.packages">packages</link>的关系类似。</para>  
    187 187 </callout>  
    188 188 <callout arearefs="soap.firststeps.1.3">  
    189   <para>You're creating the <classname>SOAPProxy</classname> with the service &url; and the service namespace.  This doesn't make any connection to the &soap; server; it simply creates a local &python; object.</para>  
      189 <para>这里你创建了包含服务 &url; 和服务命名空间的 <classname>SOAPProxy</classname>。这与 &soap; 服务器无关,仅仅是建立了一个本地 &python; 对象。</para>  
    189 189 </callout>  
    190 190 <callout arearefs="soap.firststeps.1.4">  
    191   <para>Now with everything configured properly, you can actually call remote &soap; methods as if they were local functions.  You pass arguments just like a normal function, and you get a return value just like a normal function.  But under the covers, there's a heck of a lot going on.</para>  
      191 <para>到此为止,如果你的设置完全正确,应该可以向调用本地函数一样调用远程 &soap; 方法。像给普通函数传递参数并接收返回一样,但在这背后却隐藏着很多的工作。</para>  
    191 191 </callout>  
    192 192 </calloutlist>  
    193 193 </example>  
    194   <para>Let's peek under those covers.</para>  
      194 <para>让我们看一看这些背后的工作</para>  
    194 194 </section>  
    195 195  
    196 196 <section id="soap.debug">  
    197 197 <?dbhtml filename="soap_web_services/debugging.html"?>  
    198   <title>Debugging &soap; Web Services</title>  
      198 <title> &soap; 网络服务查错</title>  
    198 198 <abstract>  
    199 199 <title/>  
    200   <para>The &soap; libraries provide an easy way to see what's going on behind the scenes.</para>  
      200 <para> &soap; 提供了一个很方便的方法用以查看背后的情形。</para>  
    200 200 </abstract>  
    201   <para>Turning on debugging is a simple matter of setting two flags in the <classname>SOAPProxy</classname>'s configuration.</para>  
      201 <para><classname>SOAPProxy</classname>的两个小设置就可以打开查错模式。</para>  
    201 201 <example>  
    202   <title>Debugging &soap; Web Services</title>  
      202 <title> &soap; 网络服务查错</title>  
    202 202 <screen>  
    203 203 &prompt;<userinput>from SOAPpy import SOAPProxy</userinput>  
     
    250 250 <calloutlist>  
    251 251 <callout arearefs="soap.debug.1.1">  
    252   <para>First, create the <classname>SOAPProxy</classname> like normal, with the service &url; and the namespace.</para>  
      252 <para>首先,正常建立带有服务 &url; 和命名空间的 <classname>SOAPProxy</classname>。</para>  
    252 252 </callout>  
    253 253 <callout arearefs="soap.debug.1.2">  
    254   <para>Second, turn on debugging by setting <varname>server.config.dumpSOAPIn</varname> and <varname>server.config.dumpSOAPOut</varname>.</para>  
      254 <para>然后,通过设置 <varname>server.config.dumpSOAPIn</varname>和 <varname>server.config.dumpSOAPOut</varname>打开查错模式。</para>  
    254 254 </callout>  
    255 255 <callout arearefs="soap.debug.1.3">  
    256   <para>Third, call the remote &soap; method as usual.  The &soap; library will print out both the outgoing XML request document, and the incoming XML response document.  This is all the hard work that <classname>SOAPProxy</classname> is doing for you.  Intimidating, isn't it?  Let's break it down.</para>  
      256 <para>最后,正常调用远程 &soap; 方法。&soap; 库将会输出送出的 XML 请求文档和收到的 XML 返回文档。这是 <classname>SOAPProxy</classname> 为你做的所有工作。 有点恐怖,不是吗?让我们来分析一下。</para>  
    256 256 </callout>  
    257 257 </calloutlist>  
    258 258 </example>  
    259   <para>Most of the XML request document that gets sent to the server is just boilerplate.  Ignore all the namespace declarations; they're going to be the same (or similar) for all &soap; calls.  The heart of the <quote>function call</quote> is this fragment within the <sgmltag>&lt;Body></sgmltag> element:</para>  
      259 <para>大部分 XML 请求文档都基于样板文件。 忽略所有命名空间声明这些对于所有 &soap; 调用都一成不变的东西。这个<quote>函数调用</quote>的核心是<sgmltag>&lt;Body></sgmltag>当中的部分:</para>  
    259 259 <informalexample>  
    260 260 <programlisting>  
     
    271 271 <calloutlist>  
    272 272 <callout arearefs="soap.debug.2.1">  
    273   <para>The element name is the function name, <function>getTemp</function>.  <classname>SOAPProxy</classname> uses <link linkend="kgp.handler">&getattr; as a dispatcher</link>.  Instead of calling separate local methods based on the method name, it actually uses the method name to construct the XML request document.</para>  
      273 <para>这个元素名<function>getTemp</function>就是函数名。<classname>SOAPProxy</classname> 把 <link linkend="kgp.handler">&getattr; 当作一个发报机</link>。有别使用方法名分别调用本地方法,这里使用方法名构造了一个 XML 请求文档。</para>  
    273 273 </callout>  
    274 274 <callout arearefs="soap.debug.2.2">  
    275   <para>The function's XML element is contained in a specific namespace, which is the namespace you specified when you created the <classname>SOAPProxy</classname> object.  Don't worry about the <literal>SOAP-ENC:root</literal>; that's boilerplate too.</para>  
      275 <para>函数的 XML 元素被存储于一个特别的命名空间,这个命名空间就是你在建立 <classname>SOAPProxy</classname> 对象时所指定的那个命名空间。也不必为 <literal>SOAP-ENC:root</literal> 而苦恼,因为它也是基于样板文件的。</para>  
    275 275 </callout>  
    276 276 <callout arearefs="soap.debug.2.3">  
    277   <para>The arguments of the function also got translated into XML.  <classname>SOAPProxy</classname> introspects each argument to determine its datatype (in this case it's a string).  The argument datatype goes into the <literal>xsi:type</literal> attribute, followed by the actual string value.</para>  
      277 <para>函数的参数也被记入 XML 文档。  <classname>SOAPProxy</classname> 查看并确定每个参数的数据类型(这里是string字符串类型)。参数的数据类型记入 <literal>xsi:type</literal> 属性,并在其后记入实际的字符串值。</para>  
    277 277 </callout>  
    278 278 </calloutlist>  
    279 279 </informalexample>  
    280   <para>The XML return document is equally easy to understand, once you know what to ignore.  Focus on this fragment within the <sgmltag>&lt;Body></sgmltag>:</para>  
      280 <para>返回的 XML 文档同样容易理解,重点在于知道应该忽略掉哪些内容。把注意力集中在 <sgmltag>&lt;Body></sgmltag>部分:</para>  
    280 280 <informalexample>  
    281 281 <programlisting>  
     
    292 292 <calloutlist>  
    293 293 <callout arearefs="soap.debug.3.1">  
    294   <para>The server wraps the function return value within a <sgmltag>&lt;getTempResponse></sgmltag> element.  By convention, this wrapper element is the name of the function, plus <literal>Response</literal>.  But it could really be almost anything; the important thing that <classname>SOAPProxy</classname> notices is not the element name, but the namespace.</para>  
      294 <para>服务器传回的值记录在<sgmltag>&lt;getTempResponse></sgmltag> 部分的几行中。 通常包括函数名和 <literal>回应(Response)</literal>。当然其他的内容也可能出现在这里,但 <classname>SOAPProxy</classname> 所重视的不是这里的元素名,而是命名空间。</para>  
    294 294 </callout>  
    295 295 <callout arearefs="soap.debug.3.2">  
    296   <para>The server returns the response in the same namespace we used in the request, the same namespace we specified when we first create the <classname>SOAPProxy</classname>.  Later in this chapter we'll see what happens if you forget to specify the namespace when creating the <classname>SOAPProxy</classname>.</para>  
      296 <para>服务器返回时所使用的命名空间就是在请求时所用的命名空间,也就是在创建 <classname>SOAPProxy</classname>对象时所指定的命名空间。本章稍后的部分中,我们将看到在创建 <classname>SOAPProxy</classname> 对象时忘记指定功能名空间会怎样。</para>  
    296 296 </callout>  
    297 297 <callout arearefs="soap.debug.3.3">  
    298   <para>The return value is specified, along with its datatype (it's a float).  <classname>SOAPProxy</classname> uses this explicit datatype to create a &python; object of the correct native datatype and return it.</para>  
      298 <para>这是返回值和它的数据类型(浮点float类型)。 <classname>SOAPProxy</classname> 使用显性数据类型创建一个原始数据类型的 &python; 对象并返回之。</para>  
    298 298 </callout>  
    299 299 </calloutlist>  
     
    306 306 <section id="soap.wsdl">  
    307 307 <?dbhtml filename="soap_web_services/wsdl.html"?>  
    308   <title>Introducing &wsdl;</title>  
      308 <title>&wsdl; 介绍</title>  
    308 308 <abstract>  
    309 309 <title/>  
    310   <para>The <classname>SOAPProxy</classname> class proxies local method calls and transparently turns then into invocations of remote &soap; methods.  As you've seen, this is a lot of work, and <classname>SOAPProxy</classname> does it quickly and transparently.  What it doesn't do is provide any means of method introspection.</para>  
      310 <para><classname>SOAPProxy</classname> 类本地方法调用并透明地转向到远程 &soap; 方法。 正如你所看到的,这是很多的工作,<classname>SOAPProxy</classname> 快速和透明地完成他们。它没有做到的是提供任何方法自省的手段。</para>  
    310 310 </abstract>  
    311   <para>Consider this: the previous two sections showed an example of calling a simple remote &soap; method with one argument and one return value, both of simple data types.  This required knowing, and keeping track of, the service &url;, the service namespace, the function name, the number of arguments, and the datatype of each argument.  If any of these is missing or wrong, the whole thing falls apart.</para>  
    312   <para>That shouldn't come as a big surprise.  If I wanted to call a local function, I would need to know what package or module it was in (the equivalent of service &url; and namespace).  I would need to know the correct function name and the correct number of arguments.  &python; deftly handles datatyping without explicit types, but I would still need to know how many argument to pass, and how many return values to expect.</para>  
    313   <para>The big difference is introspection.  As you saw in <xref linkend="apihelper" endterm="apihelper.numberonly"/>, &python; excels at letting you discover things about modules and functions at runtime.  You can list the available functions within a module, and with a little work, drill down to individual function declarations and arguments.</para>  
    314   <para>&wsdl; lets you do that with &soap; web services.  &wsdl; stands for <quote>Web Services Description Language</quote>.  Although designed to be flexible enough to describe many types of web services, it is most often used to describe &soap; web services.</para>  
    315   <para>A &wsdl; file is just that: a file.  More specifically, it's an XML file.  It usually lives on the same server you use to access the &soap; web services it describes, although there's nothing special about it.  Later in this chapter, we'll download the &wsdl; file for the Google API and use it locally.  That doesn't mean we're calling Google locally; the &wsdl; file still describes the remote functions sitting on Google's server.</para>  
    316   <para>A &wsdl; file contains a description of everything involved in calling a &soap; web service:</para>  
      311 <para>试想一下:前面两部分所展现的调用只有一个参数和返回的简单远程 &soap; 方法。服务 &url;和一系列参数及它们的数据类型需要被知道并跟踪。任何的缺失或错误都会导致整体的失败。</para>  
      312 <para>这并没有什么可惊讶的。如果我要调用一个本地函数,我需要知道函数所在的包和模块名(与之对应的则是服务 &url;he 命名空间)。我还需要知道正确的函数名以及其函数个数。 &python; 精妙地在不需要明示类型,但我还是需要知道有多少个参数需要传递,多少个值将被返回。</para>  
      313 <para>最大的区别就在于内省。 就像你在 <xref linkend="apihelper" endterm="apihelper.numberonly"/>看到的那样, &python; 擅长于让你实时地去探索模块和函数的情况。你可以对一个模块中的所有函数进行列表,并不费吹灰之力地明了函数的声明和参数情况。</para>  
      314 <para>&wsdl; 允许你对 &soap; 网络服务做相同的事情。 &wsdl; 是 <quote>网络服务描述语言(Web Services Description Language)</quote>的缩写。 尽管是为自如地表述多种类型的网络服务而设定,却也经常用于描述 &soap; 网络服务。</para>  
      315 <para>一个 &wsdl; 文件不过就是一个文件。 更具体地讲,是一个 XML 文件。通常存储于你所访问的 &soap; 网络服务这个被描述对象所在的服务器上,并没有什么特殊之处。 在本章稍后的位置,我们将下载Google API的 &wsdl; 文件并在本地使用它。 这并不意味着本地调用Google, 这个 &wsdl; 文件所描述的仍旧是Google服务器上的远程函数。</para>  
      316 <para>在 &wsdl; 文件中描述了调用相应的 &soap; 网络服务的一切:</para>  
    317 317 <itemizedlist>  
    318   <listitem><para>The service &url; and namespace</para></listitem>  
    319   <listitem><para>The type of web service (probably function calls using &soap;, although as I mentioned, &wsdl; is flexible enough to describe a wide variety of web services)</para></listitem>  
    320   <listitem><para>The list of available functions</para></listitem>  
    321   <listitem><para>The arguments for each function</para></listitem>  
    322   <listitem><para>The datatype of each argument</para></listitem>  
    323   <listitem><para>The return values of each function, and the datatype of each return value</para></listitem>  
      318 <listitem><para>服务 &url; 和命名空间</para></listitem>  
      319 <listitem><para>网络服务的类型(可能还包括 &soap; 的函数调用,正像我所说过的,&wsdl; 足够自如地去描述网络服务的广泛内容)</para></listitem>  
      320 <listitem><para>有效函数列表</para></listitem>  
      321 <listitem><para>每个函数的参数</para></listitem>  
      322 <listitem><para>每个参数的类型</para></listitem>  
      323 <listitem><para>每个函数的返回值及其数据类型</para></listitem>  
    324 324 </itemizedlist>  
    325   <para>In other words, a &wsdl; file tells you everything you need to know to be able to call a &soap; web service.</para>  
      325 <para>换言之,一个 &wsdl; 文件告诉你调用 &soap; 所需要知道的一切。</para>  
    325 325 </section>  
    326 326  
     
    333 333 <abstract>  
    334 334 <title/>  
    335   <para>Like many things in the web services arena, &wsdl; has a long and checkered history, full of political strife and intrigue.  I will skip over this history entirely, since it bores me to tears.  There were other standards that tried to do similar things, but &wsdl; won, so let's learn how to use it.</para>  
      335 <para>就像网络服务舞台上的所有事物, &wsdl; 也经历了一个充满明争暗斗而且漫长多变的历史。 我不打算讲述这段令我伤心的历史。 还有一些其他的标准提供相同的支持,但 &wsdl; 还是胜出,所以我们还是来学习一下如何使用它。</para>  
    335 335 </abstract>  
    336   <para>The most fundamental thing that &wsdl; allows you to do is discover the available methods offered by a &soap; server.</para>  
      336 <para>&wsdl; 最基本的功能便是让你揭示 &soap; 服务器所提供的有效方法。</para>  
    336 336 <example>  
    337   <title>Discovering The Available Methods</title>  
      337 <title>揭示有效方法</title>  
    337 337 <screen>  
    338 338 &prompt;<userinput>from SOAPpy import WSDL</userinput>          <co id="soap.introspection.1.1"/>  
     
    347 347 <calloutlist>  
    348 348 <callout arearefs="soap.introspection.1.1">  
    349   <para>&soappy; includes a &wsdl; parser.  At the time of this writing, it was labeled as being in the early stages of development, but I had no problem parsing any of the &wsdl; files I tried.</para>  
      349 <para>&soappy; 包含一个 &wsdl; 解析器。 在本书写作之时,它被标示为开发的初级阶段,但我从来没有在解析任何 &wsdl; 文件时遇到问题。</para>  
    349 349 </callout>  
    350 350 <callout arearefs="soap.introspection.1.2">  
    351   <para>To use a &wsdl; file, you again use a proxy class, <classname>WSDL.Proxy</classname>, which takes a single argument: the &wsdl; file.  Note that in this case you are passing in the &url; of a &wsdl; file stored on the remote server, but the proxy class works just as well with a local copy of the &wsdl; file.  The act of creating the &wsdl; proxy will download the &wsdl; file and parse it, so it there are any errors in the &wsdl; file (or it can't be fetched due to networking problems), you'll know about it immediately.</para>  
      351 <para>使用一个 &wsdl; 文件,你还是要用到一个 proxy 类:<classname>WSDL.Proxy</classname>,它只有一个参数: &wsdl; 文件。 我所说的是把存储在远程服务器上的 &wsdl; 的 &url;, 但是这个 proxy 类对于本地的 &wsdl; 副本工作同样出色。创建 &wsdl; proxy 将会下载 &wsdl; 文件并解析它, 所以如果 &wsdl; 文件有任何问题(或者由于网络问题不能获得)你会立刻知道。</para>  
    351 351 </callout>  
    352 352 <callout arearefs="soap.introspection.1.3">  
    353   <para>The &wsdl; proxy class exposes the available functions as a &python; dictionary, <varname>server.methods</varname>.  So getting the list of available methods is as simple as calling the dictionary method <methodname>keys()</methodname>.</para>  
      353 <para> &wsdl; proxy 类以 &python; 字典<varname>server.methods</varname>的方式揭示有效函数。所以列表有效方法就像调用字典方法<methodname>keys()</methodname>一样简单。</para>  
    353 353 </callout>  
    354 354 </calloutlist>  
    355 355 </example>  
    356   <para>Okay, so you know that this &soap; server offers a single method: <methodname>getTemp</methodname>.  But how do you call it?  The &wsdl; proxy object can tell you that too.</para>  
      356 <para>好的,你知道这个 &soap; 服务器提供一个方法: <methodname>getTemp</methodname>。但是如何去调用它呢? &wsdl;  也在这方面提供信息。</para>  
    356 356 <example>  
    357   <title>Discovering A Method's Arguments</title>  
      357 <title>揭示一个方法的参数</title>  
    357 357 <screen>  
    358 358 &prompt;<userinput>callInfo = server.methods['getTemp']</userinput>  <co id="soap.introspection.2.1"/>  
     
    371 371 <calloutlist>  
    372 372 <callout arearefs="soap.introspection.2.1">  
    373   <para>The <varname>server.methods</varname> dictionary is filled with a &soappy;-specific structure called <classname>CallInfo</classname>.  A <classname>CallInfo</classname> object contains information about one specific function, including the function arguments.</para>  
      373 <para> <varname>server.methods</varname> 字典中记录一个 &soappy;的特别结构,被称为<classname>CallInfo</classname>.  <classname>CallInfo</classname> 对象中包含着特定函数和函数参数的信息</para>  
    373 373 </callout>  
    374 374 <callout arearefs="soap.introspection.2.2">  
    375   <para>The function arguments are stored in <varname>callInfo.inparams</varname>, which is a &python; list of <classname>ParameterInfo</classname> objects that hold information about each parameter.</para>  
      375 <para>函数参数信息存储在<varname>callInfo.inparams</varname>中,这是一个记录每一个参数信息的<classname>ParameterInfo</classname>对象的&python;列表。</para>  
    375 375 </callout>  
    376 376 <callout arearefs="soap.introspection.2.3">  
    377   <para>Each <classname>ParameterInfo</classname> object contains a <varname>name</varname> attribute, which is the argument name.  You are not required to know the argument name to call the function through &soap;, but &soap; does support calling functions with named arguments (just like &python;), and <classname>WSDL.Proxy</classname> will correctly handle mapping named arguments to the remote function if you choose to use them.</para>  
      377 <para>每个 <classname>ParameterInfo</classname> 对象包含一个 <varname>name</varname> 属性,这便是参数名。再通过 你不需要 &soap; 调用函数时不需要知道参数名,但 &soap; 却支持在调用函数时使用参数名的情形(类似于 &python; )。如果使用参数名, <classname>WSDL.Proxy</classname> 将会正确地把这些参数关联到远程函数。</para>  
    377 377 </callout>  
    378 378 <callout arearefs="soap.introspection.2.4">  
    379   <para>Each parameter is also explicitly typed, using datatypes defined in XML Schema.  You saw this in the wire trace in the previous section; the XML Schema namespace was part of the <quote>boilerplate</quote> I told you to ignore.  For our purposes here, you may continue to ignore it.  The <varname>zipcode</varname> parameter is a string, and if you pass in a &python; string to the <classname>WSDL.Proxy</classname> object, it will map it correctly and send it to the server.</para>  
      379 <para>每个参数都是都是显性类型的,在XML Schema 中以数据类型定义。你可以在上一节中发现这一点:XML Schema 命名空间是我让你忽略的模版的一部分。就目前的而言,你还是可以继续忽略它。 <varname>zipcode</varname> 参数是一个字符串,如果你向<classname>WSDL.Proxy</classname>对象传递一个 &python; 字符串,它会被正确地关联和传递到服务器。</para>  
    379 379 </callout>  
    380 380 </calloutlist>  
    381 381 </example>  
    382   <para>&wsdl; also lets you introspect into a function's return values.</para>  
      382 <para>&wsdl; 还允许你自省函数的返回值</para>  
    382 382 <example>  
    383   <title>Discovering A Method's Return Values</title>  
      383 <title>揭示方法返回值</title>  
    383 383 <screen>  
    384 384 &prompt;<userinput>callInfo.outparams</userinput>            <co id="soap.introspection.3.1"/>  
     
    397 397 <calloutlist>  
    398 398 <callout arearefs="soap.introspection.3.1">  
    399   <para>The adjunct to <varname>callInfo.inparams</varname> for function arguments is <varname>callInfo.outparams</varname> for return value.  It is also a list, because functions called through &soap; can return multiple values, just like &python; functions.</para>  
      399 <para>与揭示函数参数的 <varname>callInfo.inparams</varname> 对应的是揭示返回值的 <varname>callInfo.outparams</varname>。它也同样是一个列表,因为通过 &soap; 调用函数时可以返回多个值,就像 &python; 函数一样。</para>  
    399 399 </callout>  
    400 400 <callout arearefs="soap.introspection.3.2">  
    401   <para>Each <classname>ParameterInfo</classname> object contains <varname>name</varname> and <varname>type</varname>.  This function returns a single value, named <varname>return</varname>, which is a float.</para>  
      401 <para> <classname>ParameterInfo</classname> 对象包含 <varname>name</varname> 和 <varname>type</varname>。这个函数返回一个浮点值,它的名字是<varname>return</varname>。</para>  
    401 401 </callout>  
    402 402 </calloutlist>  
    403 403 </example>  
    404   <para>Let's put it all together, and call a &soap; web service through a &wsdl; proxy.</para>  
      404 <para>让我们整合一下,通过 &wsdl; proxy 调用一个 &soap; 网络服务</para>  
    404 404 <example>  
    405   <title>Calling A Web Service Through A &wsdl; Proxy</title>  
      405 <title>通过 &wsdl; proxy 调用一个 &soap; 网络服务</title>  
    405 405 <screen>  
    406 406 &prompt;<userinput>from SOAPpy import WSDL</userinput>  
     
    450 450 <calloutlist>  
    451 451 <callout arearefs="soap.introspection.4.1">  
    452   <para>The configuration is simpler than calling the &soap; service directly, since the &wsdl; file contains the both service &url; and namespace you need to call the service.  Creating the <classname>WSDL.Proxy</classname> object downloads the &wsdl; file, parses it, and configures a <classname>SOAPProxy</classname> object that it uses to call the actual &soap; web service.</para>  
      452 <para>比直接调用 &soap; 服务时的设置简单,因为在 &wsdl; 文件中包含着调用服务所需要的服务 &url; 和命名空间。创建 <classname>WSDL.Proxy</classname> 对象来下载 &wsdl; 文件,解析之,并设置一个用以调用实际的 &soap;网络服务的  <classname>SOAPProxy</classname> 对象。</para>  
    452 452 </callout>  
    453 453 <callout arearefs="soap.introspection.4.2">  
    454   <para>Once the <classname>WSDL.Proxy</classname> object is created, you can call a function as easily as you did with the <classname>SOAPProxy</classname> object.  This is not surprising; the <classname>WSDL.Proxy</classname> is just a wrapper around the <classname>SOAPProxy</classname> with some introspection methods added, so the syntax for calling functions is the same.</para>  
      454 <para> <classname>WSDL.Proxy</classname> 对象一旦被创建,你可以像调用 <classname>SOAPProxy</classname> 对象一样简单地调用一个函数。这并不奇怪,<classname>WSDL.Proxy</classname> 就是一个具有自省方法的<classname>SOAPProxy</classname>封装套,所以调用函数的语法也是一样的。</para>  
    454 454 </callout>  
    455 455 <callout arearefs="soap.introspection.4.3">  
    456   <para>You can access the <classname>WSDL.Proxy</classname>'s <classname>SOAPProxy</classname> with <varname>server.soapproxy</varname>.  This is useful to turning on debugging, so that when you can call functions through the &wsdl; proxy, its <classname>SOAPProxy</classname> will dump the outgoing and incoming XML documents that are going over the wire.</para>  
      456 <para>你可以通过<varname>server.soapproxy</varname>访问 <classname>WSDL.Proxy</classname>的 <classname>SOAPProxy</classname>。这对于打开查错模式很重要,这样一来当你通过&wsdl; proxy调用函数时,它的 <classname>SOAPProxy</classname> 将会把线路上来往的XML文档丢下来。</para>  
    456 456 </callout>  
    457 457 </calloutlist>  
     
    464 464 <section id="soap.google">  
    465 465 <?dbhtml filename="soap_web_services/google.html"?>  
    466   <title>Searching Google</title>  
      466 <title>搜索 Google</title>  
    466 466 <abstract>  
    467 467 <title/>  
    468   <para>Let's finally turn to the sample code that you saw that the beginning of this chapter, which does something more useful and exciting than get the current temperature.</para>  
      468 <para>让我们回到这章开始时你看到的那段代码,获得比当前气温更有价值和令人振奋的信息。</para>  
    468 468 </abstract>  
    469   <para>Google provides a &soap; &api; for programmatically accessing Google search results.  To use it, you will need to sign up for Google Web Services.</para>  
      469 <para>Google 提供了一个 &soap; &api; ,以便通过程序进行Google搜索。使用它的前提是,你注册了Google网络服务。</para>  
    469 469 <procedure>  
    470   <title>Signing Up for Google Web Services</title>  
    471   <step><para>Go to <ulink url="http://www.google.com/apis/"/> and create a Google account.  This requires only an email address.  After you sign up you will receive your Google API license key by email.  You will need this key to pass as a parameter whenever you call Google's search functions.</para></step>  
    472   <step><para>Also on <ulink url="http://www.google.com/apis/"/>, download the Google Web APIs developer kit.  This includes some sample code in several programming languages (but not &python;), and more importantly, it includes the &wsdl; file.</para></step>  
    473   <step><para>Decompress the developer kit file and find <filename>GoogleSearch.wsdl</filename>.  Copy this file to some permanent location on your local drive.  You will need it later in this chapter.</para></step>  
      470 <title>注册 Google 网络服务</title>  
      471 <step><para>访问 <ulink url="http://www.google.com/apis/"/> 并创建一个账号。 唯一的需要是提供一个E-mail地址。 注册之后,你将通过E-mail收到你的 Google API 许可证(license key)。 你需要在调用 Google 搜索函数时使用这个许可证。</para></step>  
      472 <step><para>还是在 <ulink url="http://www.google.com/apis/"/>上,下载 Google 网络 APIs 开发工具包(kit)。它包含着包括&python;在内的多种语言的样例代码,更重要的是它包含着 &wsdl; 文件。</para></step>  
      473 <step><para>解压这个开发工具包并找到 <filename>GoogleSearch.wsdl</filename>。将这个文件拷贝到你本地驱动器的一个永久地址。在本章后面位置你会用到它。</para></step>  
    474 474 </procedure>  
    475   <para>Once you have your developer key and your Google &wsdl; file in a known place, you can start poking around with Google Web Services.</para>  
      475 <para>你有了开发许可证和 Google &wsdl; 文件之后就可以和Google网络服务打交道了。</para>  
    475 475 <example>  
    476   <title>Introspecting Google Web Services</title>  
      476 <title>内省 Google 网络服务</title>  
    476 476 <screen>  
    477 477 &prompt;<userinput>from SOAPpy import WSDL</userinput>  
     
    500 500 <calloutlist>  
    501 501 <callout arearefs="soap.google.1.1">  
    502   <para>Getting started with Google web services is easy: just create a <classname>WSDL.Proxy</classname> object and point it at your local copy of Google's &wsdl; file.</para>  
      502 <para>步入Google 网络服务很简单:建立一个 <classname>WSDL.Proxy</classname> 对象并指向到你复制到本地的 Google &wsdl;文件。</para>  
    502 502 </callout>  
    503 503 <callout arearefs="soap.google.1.2">  
    504   <para>According to the &wsdl; file, Google offers three functions: <function>doGoogleSearch</function>, <function>doGetCachedPage</function>, and <function>doSpellingSuggestion</function>.  These do exactly what they sound like: perform a Google search and return the results programmatically, get access to the cached version of a page from the last time Google saw it, and offer spelling suggestions for commonly misspelled search words.</para>  
      504 <para>由 &wsdl; 文件可知,Google提供三个函数:<function>doGoogleSearch</function>, <function>doGetCachedPage</function>和<function>doSpellingSuggestion</function>。顾名思义,执行Google搜索并返回结果,获得Google最后一次扫描该页时获得的缓存,为基于常见拼写错误提出单词拼写建议。</para>  
    504 504 </callout>  
    505 505 <callout arearefs="soap.google.1.3">  
    506   <para>The <function>doGoogleSearch</function> function takes a number of parameters of various types.  Note that while the &wsdl; file can tell you what the arguments are called and what datatype they are, it can't tell you what they mean or how to use them.  It could theoretically tell you the acceptable range of values for each parameter, if only specific values were allowed, but Google's &wsdl; file is not that detailed.  <classname>WSDL.Proxy</classname> can't work magic; it can only give you the information provided in the &wsdl; file.</para>  
      506 <para><function>doGoogleSearch</function> 函数需要一系列不同类型的参数。注意: &wsdl; 文件可以告诉你有哪些参数和他们的参数类型,但不能告诉你它们的含义和使用方法。在参数值有限定的情况下,理论上它能够告诉你参数的取值范围,但Google的 &wsdl; 没有那么细化。 <classname>WSDL.Proxy</classname> 不会变魔术,它只能给你 &wsdl; 文件中提供的信息。</para>  
    506 506 </callout>  
    507 507 </calloutlist>  
    508 508 </example>  
    509   <para>Here is a brief synopsis of all the parameters to the <function>doGoogleSearch</function> function:</para>  
      509 <para>这里简要地列出了 <function>doGoogleSearch</function> 函数的所有参数:</para>  
    509 509 <itemizedlist>  
    510   <listitem><para><varname>key</varname> - Your Google API key, which you received when you signed up for Google web services.</para></listitem>  
    511   <listitem><para><varname>q</varname> - The search word or phrase you're looking for.  The syntax is exactly the same as Google's web form, so if you know any advanced search syntax or tricks, they all work here as well.</para></listitem>  
    512   <listitem><para><varname>start</varname> - The index of the result to start on.  Like the interactive web version of Google, this function returns 10 results at a time.  If you wanted to get the second <quote>page</quote> of results, you would set <varname>start</varname> to 10.</para></listitem>  
    513   <listitem><para><varname>maxResults</varname> - The number of results to return.  Currently capped at 10, although you can specify fewer if you are only interested in a few results and want to save a little bandwidth.</para></listitem>  
    514   <listitem><para><varname>filter</varname> - If &true;, Google will filter out duplicate pages from the results.</para></listitem>  
    515   <listitem><para><varname>restrict</varname> - Set this to <literal>country</literal> plus a country code to get results only from a particular country.  Example: <literal>countryUK</literal> to search pages in the United Kingdom.  You can also specify <literal>linux</literal>, <literal>mac</literal>, or <literal>bsd</literal> to search a Google-defined set of technical sites, or <literal>unclesam</literal> to search sites about the United States government.</para></listitem>  
    516   <listitem><para><varname>safeSearch</varname> - If &true;, Google will filter out porn sites.</para></listitem>  
    517   <listitem><para><varname>lr</varname> (<quote>language restrict</quote>) - Set this to a language code to get results only in a particular language.</para></listitem>  
    518   <listitem><para><varname>ie</varname> and <varname>oe</varname> (<quote>input encoding</quote> and <quote>output encoding</quote>) - Deprecated, both must be <literal>utf-8</literal>.</para></listitem>  
      510 <listitem><para><varname>key</varname> —— 你注册Google网络服务时获得的Google API 许可证。</para></listitem>  
      511 <listitem><para><varname>q</varname> - 你要搜索的词或词组。其语法与Google的网站表单处完全相同,你所知道的高级搜索语法和技巧这里完全适用。</para></listitem>  
      512 <listitem><para><varname>start</varname> —— 起始的结果编号。与使用Google网页交互搜索时相同,这个函数每次返回10个结果。如果你需要查看第二<quote></quote>页结果则需要将 <varname>start</varname> 设置为10。</para></listitem>  
      513 <listitem><para><varname>maxResults</varname> —— 返回的结果个数。目前的值是10,当然如果你只对少数返回结果感兴趣或者希望节省网络带宽,也可以定义为返回更少的结果。</para></listitem>  
      514 <listitem><para><varname>filter</varname> —— 如果设置为 &true;,Google将会过滤结果中重复的页面。</para></listitem>  
      515 <listitem><para><varname>restrict</varname> —— 这里设置 <literal>country</literal> 并跟上一个国家代码可以限定只返回特定国家的结果。例如: <literal>countryUK</literal> 用于在英国搜索页面。你也可以设定 <literal>linux</literal>, <literal>mac</literal> 或者 <literal>bsd</literal> 以便搜索Google定义的技术站点组,或者设为 <literal>unclesam</literal> 来搜索美国政府站点。</para></listitem>  
      516 <listitem><para><varname>safeSearch</varname> —— 如果设置为 &true;, Google 将会过滤掉色情站点。</para></listitem>  
      517 <listitem><para><varname>lr</varname> (<quote>语言限制</quote>) —— 这里设置语言限定值返回特定语言的站点。</para></listitem>  
      518 <listitem><para><varname>ie</varname> 和 <varname>oe</varname> (<quote>输入编码input encoding</quote> and <quote>输出编码output encoding</quote>) —— Deprecated,都应该是 <literal>utf-8</literal>.</para></listitem>  
    519 519 </itemizedlist>  
    520 520 <example>  
    521   <title>Searching Google</title>  
      521 <title>搜索 Google</title>  
    521 521 <screen>  
    522 522 &prompt;<userinput>from SOAPpy import WSDL</userinput>  
     
    539 539 <calloutlist>  
    540 540 <callout arearefs="soap.google.2.1">  
    541   <para>After setting up the <classname>WSDL.Proxy</classname> object, you can call <function>server.doGoogleSearch</function> with all ten parameters.  Remember to use your own Google API key that you received when you signed up for Google web services.</para>  
      541 <para>在设置好 <classname>WSDL.Proxy</classname> 对象之后,你可以使用十个参数来调用 <function>server.doGoogleSearch</function>。 记住在要使用你注册Google网络服务时授权给你自己的Google API 许可证。</para>  
    541 541 </callout>  
    542 542 <callout arearefs="soap.google.2.2">  
    543   <para>There's a lot of information returned, but let's look at the actual search results first.  They're stored in <varname>results.resultElements</varname>, and you can access them just like a normal &python; list.</para>  
      543 <para>有很多的返回信息,但我们还是先来看一下实际的返回结果。它们被存储于 <varname>results.resultElements</varname>之中,你可以像使用普通的 &python; 列表那样来调用它。</para>  
    543 543 </callout>  
    544 544 <callout arearefs="soap.google.2.3">  
    545   <para>Each element in the <varname>resultElements</varname> is an object that has a <varname>URL</varname>, <varname>title</varname>, <varname>snippet</varname>, and other useful attributes.  At this point you can use normal &python; introspection techniques like <userinput>dir(results.resultElements[0])</userinput> to see the available attributes.  Or you can introspect through the &wsdl; proxy object and look through the function's <varname>outparams</varname>.  Each technique will give you the same information.</para>  
      545 <para><varname>resultElements</varname>中的每个元素都是一个包含<varname>URL</varname>, <varname>title</varname>, <varname>snippet</varname>以及其他属性的对象。基于这一点,你可以使用诸如<userinput>dir(results.resultElements[0])</userinput>的普通 &python; 自省技术来查看有效属性,或者通过 &wsdl; proxy 对象查看函数的<varname>outparams</varname>。 不同的方法能带给你相同的结果。</para>  
    545 545 </callout>  
    546 546 </calloutlist>  
    547 547 </example>  
    548   <para>The <varname>results</varname> object contains more than the actual search results.  It also contains information about the search itself, such as how long it took and how many results were found (even though only 10 were returned).  The Google web interface shows this information, and you can access it programmatically too.</para>  
      548 <para> <varname>results</varname> 对象中所加载的不仅仅是实际的搜索结果。 它也含有搜索行为自身的信息,比如耗时和总结果数等(尽管只返回了10条结果)。 Google 网页界面中显示了这些信息,通过程序你也同样能获得它们。</para>  
    548 548 <example>  
    549   <title>Accessing Secondary Information From Google</title>  
      549 <title>从Google获得次要信息</title>  
    549 549 <screen>  
    550 550 &prompt;<userinput>results.searchTime</userinput>                     <co id="soap.google.3.1"/>  
     
    567 567 <calloutlist>  
    568 568 <callout arearefs="soap.google.3.1">  
    569   <para>This search took 0.224919 seconds.  That does not include the time spent sending and receiving the actual &soap; XML documents.  It's just the time that Google spent processing your request once it received it.</para>  
      569 <para>这个搜索耗时 0.224919 秒。这部包括用于发送和接收 &soap; XML 文档的时间,仅仅是Google在接到搜索请求后执行搜索所花费的时间。</para>  
    569 569 </callout>  
    570 570 <callout arearefs="soap.google.3.2">  
    571   <para>In total, there were approximately 30 million results.  You can access them 10 at a time by changing the <varname>start</varname> parameter and calling <function>server.doGoogleSearch</function> again.</para>  
      571 <para>总共有接近30,000,000个结果信息,你可以通过以10递增地改变 <varname>start</varname> 参数来重复调用 <function>server.doGoogleSearch</function> 。</para>  
    571 571 </callout>  
    572 572 <callout arearefs="soap.google.3.3">  
    573   <para>For some queries, Google also returns a list of related categories in the <ulink url="http://directory.google.com/">Google Directory</ulink>.  You can append these URLs to <ulink url="http://directory.google.com/"/> to construct the link to the directory category page.</para>  
      573 <para>对于有些请求,Google还返回一个<ulink url="http://directory.google.com/">Google Directory</ulink>中的类别列表。你可以用这些 URLs 到 <ulink url="http://directory.google.com/"/> 建立到 directory category 页面的链接。</para>  
    573 573 </callout>  
    574 574 </calloutlist>  
     
    593 593 <section id="soap.troubleshooting">  
    594 594 <?dbhtml filename="soap_web_services/troubleshooting.html"?>  
    595   <title>Troubleshooting &soap; Web Services</title>  
      595 <title> &soap; 网络服务故障排除</title>  
    595 595 <abstract>  
    596 596 <title/>  
    597   <para>Of course, the world of &soap; web services is not all happiness and light.  Sometimes things go wrong.</para>  
      597 <para>是的,&soap; 网络服务的世界中也不总是欢乐和阳光。 有时候也会有故障。</para>  
    597 597 </abstract>  
    598   <para>As you've seen throughout this chapter, &soap; involves several layers.  There's the HTTP layer, since &soap; is sending XML documents to, and receiving XML documents from, an HTTP server.  So all the debugging techniques you learned in <xref linkend="oa"/> come into play here.  You can <userinput>import httplib</userinput> and then set <userinput>httplib.HTTPConnection.debuglevel = 1</userinput> to see the underlying HTTP traffic.</para>  
    599   <para>Beyond the underlying HTTP layer, there are a number of things that can go wrong.  &soappy; does an admirable job hiding the &soap; syntax from you, but that also means it can be difficult to determine where the problem is when things don't work.</para>  
    600   <para>Here are a few examples of common mistakes that I've made in using &soap; web services, and the errors they generated.</para>  
      598 <para>正如你在此章中看到的,&soap; 牵扯了很多层面。 需要HTTP层,&soap; 需要向HTTP服务器发送XML文档并接收返回的XML文档。这样一来,你在 <xref linkend="oa"/> 学到的差错技术在这里都有了用武之地。你可以 <userinput>import httplib</userinput> 并设置<userinput>httplib.HTTPConnection.debuglevel = 1</userinput> 来查看潜在的 HTTP 传输。</para>  
      599 <para>在 HTTP 层之上,还有几个可能发生问题的地方。 &soappy; 隐藏 &soap; 语法的本领令你惊叹不已,但也意味着在发生问题时更难确定问题所在。</para>  
      600 <para>下面的这些例子是我在使用 &soap; 网络服务时犯过的一些常见错误以及所产生的错误信息。</para>  
    601 601 <example>  
    602   <title>Calling a Method With an Incorrectly Configured Proxy</title>  
      602 <title>以错误设置的 Proxy 调用方法</title>  
    602 602 <screen>  
    603 603 &prompt;<userinput>from SOAPpy import SOAPProxy</userinput>  
     
    623 623 <calloutlist>  
    624 624 <callout arearefs="soap.troubleshooting.1.1">  
    625   <para>Did you spot the mistake?  You're creating a <classname>SOAPProxy</classname> manually, and you've correctly specified the service &url;, but you haven't specified the namespace.  Since multiple services may be routed through the same service &url;, the namespace is essential to determine which service you're trying to talk to, and therefore which method you're really calling.</para>  
      625 <para>你看出错误了吗?你手工地创建了一个 <classname>SOAPProxy</classname> ,你正确地制定了服务 &url;,但是你没有指定命名空间。 由于多个服务可能被路由到相同的服务 &url;,命名空间是确定你所调用的服务和方法的重要内容。</para>  
    625 625 </callout>  
    626 626 <callout arearefs="soap.troubleshooting.1.2">  
    627   <para>The server responds by sending a &soap; Fault, which &soappy; turns into a &python; exception of type <classname>SOAPpy.Types.faultType</classname>.  All errors returned from any &soap; server will always be &soap; Faults, so you can easily catch this exception.  In this case, the human-readable part of the &soap; Fault gives a clue to the problem: the method element is not namespaced, because the original <classname>SOAPProxy</classname> object was not configured with a service namespace.</para>  
      627 <para>服务器返回的是一个 &soap; 错误,&soappy; 溢出了<classname>SOAPpy.Types.faultType</classname> 这个 &python; 异常。 从任何 &soap; 服务器返回的错误都是 &soap; 错误,因此你可以轻易地捕获这个异常。就此出而言,我们能从&soap; 错误信息中看出端倪:由于源 <classname>SOAPProxy</classname> 对象没有设置服务命名空间,因此方法元素也就没有了命名空间。</para>  
    627 627 </callout>  
    628 628 </calloutlist>  
    629 629 </example>  
    630   <para>Misconfiguring the basic elements of the &soap; service is one of the problems that &wsdl; aims to solve.  The &wsdl; file contains the service &url; and namespace, so you can't get it wrong.  Of course, there are still other things you can get wrong.</para>  
      630 <para>错误配置 &soap; 服务的基本元素是 &wsdl; 问题解决的着眼点。 &wsdl; 文件包含服务 &url; 和命名空间,所以你应该不会在这里犯错。但是,还有其他可能出错的地方。</para>  
    630 630 <example>  
    631   <title>Calling a Method With the Wrong Arguments</title>  
      631 <title>以错误参数调用方法</title>  
    631 631 <screen>  
    632 632 &prompt;<userinput>wsdlFile = 'http://www.xmethods.net/sd/2001/TemperatureService.wsdl'</userinput>  
     
    652 652 <calloutlist>  
    653 653 <callout arearefs="soap.troubleshooting.2.1">  
    654   <para>Did you spot the mistake?  It's a subtle one: you're calling <function>server.getTemp</function> with an integer instead of a string.  As you saw from introspecting the &wsdl; file, the <function>getTemp()</function> &soap; function takes a single argument, <varname>zipcode</varname>, which must be a string.  <classname>WSDL.Proxy</classname> will <emphasis>not</emphasis> coerce datatypes for you; you need to pass the exact datatypes that the server expects.</para>  
      654 <para>你看出错误了吗? 这是一个不易察觉的错误:你在使用整数而不是字符串来调用<function>server.getTemp</function> 。自省 &wsdl; 文件不难发现,<function>getTemp()</function> 这个 &soap; 函数接受一个参数 <varname>zipcode</varname>,这是一个字符串参数。 <classname>WSDL.Proxy</classname> <emphasis>不</emphasis> 会为你强制数据类型;你需要根据服务器需要的数据类型传递数据。</para>  
    654 654 </callout>  
    655 655 <callout arearefs="soap.troubleshooting.2.2">  
    656   <para>Again, the server returns a &soap; Fault, and the human-readable part of the error gives a clue as to the problem: you're calling a <function>getTemp</function> function with an integer value, but there is no function defined with that name that takes an integer.  In theory, &soap; allows you to <emphasis>overload</emphasis> functions, so you could have two functions in the same &soap; service with the same name and the same number of arguments, but the arguments were of different datatypes.  This is why it's important to match the datatypes exactly, and why <classname>WSDL.Proxy</classname> doesn't coerce datatypes for you.  If it did, you could end up calling a completely different function!  Good luck debugging that one.  It's much easier to be picky about datatypes and fail as quickly as possible if you get them wrong.</para>  
      656 <para>又是这样,服务器传回一个 &soap; 错误,你能从&soap; 错误信息中看出端倪:你在使用整数类型的参数调用 <function>getTemp</function> 函数,但却没有一个以此命名的函数接收整数参数。理论上讲, &soap; 允许你重载 <emphasis>overload</emphasis> 函数,也就是可以在同一个 &soap; 服务中存在同名函数,并且参数个数也相同,但是参数的数据类型不同。这就是数据类型必须匹配的原因,也说明了为什么 <classname>WSDL.Proxy</classname> 不强制地为你改变数据类型。如果真的强制改变了数据类型,发生这样的错误时,调用的可能是另外一个不相干的函数。看来产生这样的错误是件幸运的事。对于数据类型多加注意会让事情简单很多,一旦搞错了数据类型便立刻会发生错误。</para>  
    656 656 </callout>  
    657 657 </calloutlist>  
    658 658 </example>  
    659   <para>It's also possible to write &python; code that expects a different number of return values than the remote function actually returns.</para>  
      659 <para> &python; 所期待的返回值个数与远程函数的实际返回值个数不同是另一种可能的错误。</para>  
    659 659 <example>  
    660   <title>Calling a Method and Expecting the Wrong Number of Return Values</title>  
      660 <title>调用时方法所期待的返回值个数错误</title>  
    660 660 <screen>  
    661 661 &prompt;<userinput>wsdlFile = 'http://www.xmethods.net/sd/2001/TemperatureService.wsdl'</userinput>  
     
    672 672 <calloutlist>  
    673 673 <callout arearefs="soap.troubleshooting.3.1">  
    674   <para>Did you spot the mistake?  <function>server.getTemp</function> only returns one value, a float, but you've written code that assumes you're getting two values and trying to assign them to two different variables.  Note that this does not fail with a &soap; fault.  As far as the remote server is concerned, nothing went wrong at all.  The error only occurred <emphasis>after</emphasis> the &soap; transaction was complete, <classname>WSDL.Proxy</classname> returned a float, and your local &python; interpreter tried to accomodate your request to split it into two different variables.  Since the function only returned one value, you get a &python; exception trying to split it, not a &soap; Fault.</para>  
      674 <para>你看出错误了吗? <function>server.getTemp</function> 只返回一个浮点值,但你写的代码却期待着获得两个值,并把它们赋值给不同的两个变量。注意这不是一个 &soap; 错误。就远程服务器而言没有发生任何错误。错误发生在完成 &soap; 交割<emphasis>之后</emphasis>。 <classname>WSDL.Proxy</classname> 返回一个浮点数,你本地的 &python; 解释器试图将这个浮点数分成两个变量。由于函数只返回了一个值,你在试图分割它时所获得的是一个 &python; 异常,而不是 &soap; 错误。</para>  
    674 674 </callout>  
    675 675 </calloutlist>  
    676 676 </example>  
    677   <para>What about Google's web service?  The most common problem I've had with it is that I forget to set the application key properly.</para>  
      677 <para>那末 Google 网络服务方面又如何呢?最常见的错误是我曾经犯过的忘记正确设置应用许可证错误。</para>  
    677 677 <example>  
    678   <title>Calling a Method With An Application-Specific Error</title>  
      678 <title>调用方法返回一个应用指定错误</title>  
    678 678 <screen>  
    679 679 &prompt;<userinput>from SOAPpy import WSDL</userinput>  
     
    757 757 <calloutlist>  
    758 758 <callout arearefs="soap.troubleshooting.4.1">  
    759   <para>Can you spot the mistake?  There's nothing wrong with the calling syntax, or the number of arguments, or the datatypes.  The problem is application-specific: the first argument is supposed to be my application key, but <literal>foo</literal> is not a valid Google key.</para>  
      759 <para>你看出错误了吗? 调用的语法,参数个数以及数据类型都没有错误。 问题在于应用指定:第一个参数应该是我的应用许可证,但 <literal>foo</literal> 不是一个有效的 Google 许可证。</para>  
    759 759 </callout>  
    760 760 <callout arearefs="soap.troubleshooting.4.2">  
    761   <para>The Google server responds with a &soap; Fault and an incredibly long error message, which includes a complete Java stack trace.  Remember that <emphasis>all</emphasis> &soap; errors are signified by &soap; Faults: errors in configuration, errors in function arguments, and application-specific errors like this.  Buried in there somewhere is the crucial piece of information: <literal>Invalid authorization key: foo</literal>.</para>  
      761 <para>Google服务器返回的是一个 &soap; 错误和一大串特别长的错误信息,其中包含了完整的Java堆栈跟踪。 记住 <emphasis>所有</emphasis>的 &soap; 错误都被标示为 &soap; 错误:设置错误,函数参数错误以及应用指定错误等等。在其中埋藏的至关重要信息确是:<literal>非有效授权许可证:foo  
      762 (Invalid authorization key: foo)</literal>。</para>  
    762 763 </callout>  
    763 764 </calloutlist>  
    764 765 </example>  
    765 766 <itemizedlist role="furtherreading">  
    766   <title>Further Reading on Troubleshooting &soap;</title>  
    767   <listitem><para><ulink url="http://www-106.ibm.com/developerworks/webservices/library/ws-pyth17.html">New developments for &soappy;</ulink> steps through trying to connect to another &soap; service that doesn't quite work as advertised.</para></listitem>  
      767 <title> &soap; 故障排除的进一步阅读</title>  
      768 <listitem><para><ulink url="http://www-106.ibm.com/developerworks/webservices/library/ws-pyth17.html">New developments for &soappy;</ulink> 一步步连接到另一个不名副其实的 &soap; 服务。</para></listitem>  
    768 769 </itemizedlist>  
    769 770 </section>  
    772 773 <section id="soap.summary">  
    773 774 <?dbhtml filename="soap_web_services/summary.html"?>  
    774   <title>Summary</title>  
      775 <title>总结</title>  
    774 775 <abstract>  
    775 776 <title/>  
    776   <para>&soap; web services are very complicated.  The specification is very ambitious and tries to cover many different use cases for web services.  This chapter has touched on some of the simpler use cases.</para>  
      777 <para>&soap; 网络服务是很复杂的,雄心勃勃的它试图涵盖网络服务的很多不同应用。这一章我们接触了它的一个简单应用。</para>  
    776 777 </abstract>  
    777 778 <highlights>  
    778   <para>Before diving into the next chapter, make sure you're comfortable doing all of these things:</para>  
      779 <para>在开始下一章的学习之前,确保你能自如地做如下工作:</para>  
    778 779 <itemizedlist>  
    779   <listitem><para>Connecting to a &soap; server and calling remote methods</para></listitem>  
    780   <listitem><para>Loading a &wsdl; file and introspecting remote methods</para></listitem>  
    781   <listitem><para>Debugging &soap; calls with wire traces</para></listitem>  
    782   <listitem><para>Troubleshooting common &soap;-related errors</para></listitem>  
      780 <listitem><para>连接到 a &soap; 服务器并调用远程方法</para></listitem>  
      781 <listitem><para>通过 &wsdl; 文件自省远程方法</para></listitem>  
      782 <listitem><para>有效排除 &soap; 调用中的错误</para></listitem>  
      783 <listitem><para>排除常见的 &soap; 相关错误</para></listitem>  
    783 784 </itemizedlist>  
    784 785 </highlights>  
  • zh-translations/branches/diveintopython-zh-5.4/zh-cn/xml/bookinfo.xml

    r259 r832  
    761 761 </revhistory>  
    762 762 <legalnotice>  
    763   <para>允许在遵守 <acronym>GNU</acronym> 自由文档许可证(GNU Free Documentation License,版本1.1或由自由软件基金会公布的最新版本)条款的规定下,拷贝,发布,并且/或者修改这个文档。本文档没有不可变部分,没有封面文字,没有封底文字。在<xref linkend="gfdl"/>中包含了此许可证的一份拷贝。</para>  
    764   <para>在这本书中的例程是自由软件。你可以在遵守 &python; 许可证(&python; 软件基金会发布)条款的规定下,重新发布,并且/或者修改它们。在<xref linkend="license"/>中包含了此许可证的一份拷贝。</para>  
    765   <para>本译本由limodou(limodou AT gmail.com), Osmond(sinosmond AT gmail.com), YuLin(yulin724 AT gmail.com), Zoom.Quiet(zoom.quiet AT gmail.com)等翻译。由 Zoom.Quiet(zoom.quiet AT gmail.com) 负责项目管理。感谢<ulink url="http://www.woodpecker.org.cn">啄木鸟社区</ulink>提供svn和项目空间。本译文遵守GFDL的规定。你可以拷贝,发布,修改此文档,但请保留此版权信息。</para>  
      763 <para>允许在遵守 <acronym>GNU</acronym> 自由文档许可证 (GNU Free Documentation License,版本1.1或由自由软件基金会公布的最新版本) 条款的规定下,拷贝,发布,并且/或者修改这个文档。本文档没有不可变部分,没有封面文字,没有封底文字。在 <xref linkend="gfdl"/> 中包含了此许可证的一份拷贝。</para>  
      764 <para>在这本书中的例程是自由软件。你可以在遵守 &python; 许可证 (&python; 软件基金会发布) 条款的规定下,重新发布,并且/或者修改它们。在 <xref linkend="license"/> 中包含了此许可证的一份拷贝。</para>  
      765 <para>本译本由 Zoom.Quiet 负责项目管理。感谢 <ulink url="http://www.woodpecker.org.cn">啄木鸟社区</ulink> 提供 <ulink url="http://cvs.woodpecker.org.cn/trac/browser/zh-translations/branches/diveintopython-zh-5.4/">SVN项目空间</ulink> 和 <ulink url="http://wiki.woodpecker.org.cn/moin/DiveIntoPythonZh">WIKI协作空间</ulink>。参加翻译的人员有:</para>  
      766 <itemizedlist>  
      767 <listitem><para>limodou (limodou AT gmail DOT com)</para></listitem>  
      768 <listitem><para>Zoom.Quiet (zoom.quiet AT gmail DOT com)</para></listitem>  
      769 <listitem><para>Jason Xie (jason AT sinoesl DOT org)</para></listitem>  
      770 <listitem><para>YuLin (yulin724 AT gmail DOT com)</para></listitem>  
      771 <listitem><para>Weigang LI (dimens AT gmail DOT com)</para></listitem>  
      772 <listitem><para>wolfg (wolfg1969 AT gmail DOT com)</para></listitem>  
      773 <listitem><para>Osmond (sinosmond AT gmail DOT com)</para></listitem>  
      774 </itemizedlist>  
      775 <para>本译文遵守 GFDL 的规定。你可以拷贝,发布,修改此文档,但请保留此版权信息。</para>  
    766 776 </legalnotice>  
    767 777 <!--  
    768 778 A brief word about the licensing of this book.  This is a free (as in speech)  
    769 779 book.  If you've heard of free software, this is the same idea, only with a book  
    770   instead of a computer program.  You now own this book, and while  
      780 instead of a computer program.  You now own this book,  while  
    770 780 you can't just do anything you want with it, you have an enormous amount of freedom,  
    771 781 much more than you would ordinarily expect to get with a book.  
     
    774 784 You can, for instance, make any number of copies of this book.  Give it to your friends,  
    775 785 post it on your own web site, publish it in new media formats.  You can even  
    776   add chapters to the book and republish it under a new title without my  
    777   consent or even my awareness.  My work is always copyright to me, and your work is  
    778   always copyright to you, and your new-and-presumably-improved version must be published  
      786 add chapters to the book 和 republish it under a new title without my  
      787 consent or even my awareness.  My work is always copyright to me, 和 your work is  
      788 always copyright to you, 和 your new-and-presumably-improved version must be published  
    779 789 under the same license as this one.  There are a few other obscure details that you  
    780 790 can read all about in the appendix, but that's the basic idea.  
    784 794 publishing them.  That never has to happen to free books.  You have the freedom to keep  
    785 795 this book alive.  If I choose to stop distributing it, you can distribute it yourself.  
    786   If I move on and this book goes out of date, you can pick up where I left off and keep  
    787   this book current and relevant.  
      796 If I move on 和 this book goes out of date, you can pick up where I left off 和 keep  
      797 this book current 和 relevant.  
    788 798  
    789   As I write this, the year is 2000, and the Internet is a battleground of intellectual  
      799 As I write this, the year is 2000,  the Internet is a battleground of intellectual  
    789 799 property disputes.  Some people would like you to believe that, without proper financial  
    790   incentives, music, literature, and computer software would disappear.  After all,  
      800 incentives, music, literature,  computer software would disappear.  After all,  
    790 800 who would make music if they can't make money on it?  Who would write?  Who would  
    791 801 program?  I know the answer.  The answer is that musicians will make music, not because