This file is indexed.

/usr/share/doc/diveintopython-zh/html/scripts_and_streams/index.html is in diveintopython-zh 5.4b-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
<!DOCTYPE html
  PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   
      <title>&nbsp;10&nbsp;&nbsp;脚本和流</title>
      <link rel="stylesheet" href="../diveintopython.css" type="text/css">
      <link rev="made" href="mailto:f8dy@diveintopython.org">
      <meta name="generator" content="DocBook XSL Stylesheets V1.52.2">
      <meta name="keywords" content="Python, Dive Into Python, tutorial, object-oriented, programming, documentation, book, free">
      <meta name="description" content="Python from novice to pro">
      <link rel="home" href="../toc/index.html" title="Dive Into Python">
      <link rel="up" href="../toc/index.html" title="Dive Into Python">
      <link rel="previous" href="../xml_processing/summary.html" title="9.7.&nbsp;Segue ">
      <link rel="next" href="stdin_stdout_stderr.html" title="10.2.&nbsp;标准输入、输出和错误">
   </head>
   <body>
      <table id="Header" width="100%" border="0" cellpadding="0" cellspacing="0" summary="">
         <tr>
            <td id="breadcrumb" colspan="5" align="left" valign="top">导航:<a href="../index.html">起始页</a>&nbsp;&gt;&nbsp;<a href="../toc/index.html">Dive Into Python</a>&nbsp;&gt;&nbsp;<span class="thispage">脚本和流</span></td>
            <td id="navigation" align="right" valign="top">&nbsp;&nbsp;&nbsp;<a href="../xml_processing/summary.html" title="上一页: “Segue ”">&lt;&lt;</a>&nbsp;&nbsp;&nbsp;<a href="stdin_stdout_stderr.html" title="下一页: “标准输入、输出和错误”">&gt;&gt;</a></td>
         </tr>
         <tr>
            <td colspan="3" id="logocontainer">
               <h1 id="logo"><a href="../index.html" accesskey="1">深入 Python :Dive Into Python 中文版</a></h1>
               <p id="tagline">Python 从新手到专家 [Dip_5.4b_CPyUG_Release]</p>
            </td>
            <td colspan="3" align="right">
               <form id="search" method="GET" action="http://www.google.com/custom">
                  <p><label for="q" accesskey="4">Find:&nbsp;</label><input type="text" id="q" name="q" size="20" maxlength="255" value=""> <input type="submit" value="搜索"><input type="hidden" name="domains" value="woodpecker.org.cn"><input type="hidden" name="sitesearch" value="www.woodpecker.org.cn/diveintopython"></p>
               </form>
            </td>
         </tr>
      </table>
      <!--#include virtual="/inc/ads" -->
      <div class="chapter" lang="zh_cn">
         <div class="titlepage">
            <div>
               <div>
                  <h2 class="title"><a name="streams"></a>&nbsp;10&nbsp;&nbsp;脚本和流
                  </h2>
               </div>
            </div>
            <div></div>
         </div>
         <div class="toc">
            <ul>
               <li><span class="section"><a href="index.html#kgp.openanything">10.1. 抽象输入源</a></span></li>
               <li><span class="section"><a href="stdin_stdout_stderr.html">10.2. 标准输入、输出和错误</a></span></li>
               <li><span class="section"><a href="caching.html">10.3. 查询缓冲节点</a></span></li>
               <li><span class="section"><a href="child_nodes.html">10.4. 查找节点的直接子节点</a></span></li>
               <li><span class="section"><a href="handlers_by_node_type.html">10.5. 根据节点类型创建不同的处理器</a></span></li>
               <li><span class="section"><a href="command_line_arguments.html">10.6. 处理命令行参数</a></span></li>
               <li><span class="section"><a href="all_together.html">10.7. 全部放在一起</a></span></li>
               <li><span class="section"><a href="summary.html">10.8. 小结</a></span></li>
            </ul>
         </div>
         <div class="section" lang="zh_cn">
            <div class="titlepage">
               <div>
                  <div>
                     <h2 class="title"><a name="kgp.openanything"></a>10.1.&nbsp;抽象输入源
                     </h2>
                  </div>
               </div>
               <div></div>
            </div>
            <div class="abstract">
               <p><span class="application">Python</span> 的最强大力量之一是它的动态绑定,而动态绑定最强大的用法之一是<span class="emphasis"><em>类文件(file-like)对象</em></span></p>
            </div>
            <p>许多需要输入源的函数可以只接收一个文件名,并以读方式打开文件,读取文件,处理完成后关闭它。其实它们不是这样的,而是接收一个<span class="emphasis"><em>类文件对象</em></span></p>
            <p>在最简单的例子中,<span class="emphasis"><em>类文件对象</em></span> 是任意一个带有 <tt class="function">read</tt> 方法的对象,这个方法带有一个可选的 <tt class="varname">size</tt> 参数,并返回一个字符串。调用时如果没有 <tt class="varname">size</tt> 参数,它从输入源中读取所有东西并将所有数据作为单个字符串返回;调用时如果指定了 <tt class="varname">size</tt> 参数,它将从输入源中读取 <tt class="varname">size</tt> 大小的数据并返回这些数据;再次调用的时候,它从余下的地方开始并返回下一块数据。
            </p>
            <p>这就是<a href="../file_handling/file_objects.html" title="6.2.&nbsp;与文件对象共事">从真实文件读取数据</a>的工作方式;区别在于你不用把自己局限于真实的文件。输入源可以是任何东西:磁盘上的文件,甚至是一个硬编码的字符串。只要你将一个类文件对象传递给函数,函数只是调用对象的 <tt class="function">read</tt> 方法,就可以处理任何类型的输入源,而不需要为处理每种类型分别编码。
               
            </p>
            <p>你可能会纳闷,这和 <span class="acronym">XML</span> 处理有什么关系。其实 <tt class="function">minidom.parse</tt> 就是一个可以接收类文件对象的函数。
            </p>
            <div class="example"><a name="d0e25285"></a><h3 class="title">&nbsp;10.1.&nbsp;从文件中解析 <span class="acronym">XML</span></h3><pre class="screen">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class='pykeyword'>from</span> xml.dom <span class='pykeyword'>import</span> minidom</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">fsock = open(<span class='pystring'>'binary.xml'</span>)</span>    <a name="kgp.openanything.1.1"></a><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">xmldoc = minidom.parse(fsock)</span> <a name="kgp.openanything.1.2"></a><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">fsock.close()</span>                 <a name="kgp.openanything.1.3"></a><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class='pykeyword'>print</span> xmldoc.toxml()</span>          <a name="kgp.openanything.1.4"></a><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12">
<span class="computeroutput">&lt;?xml version="1.0" ?&gt;
&lt;grammar&gt;
&lt;ref id="bit"&gt;
  &lt;p&gt;0&lt;/p&gt;
  &lt;p&gt;1&lt;/p&gt;
&lt;/ref&gt;
&lt;ref id="byte"&gt;
  &lt;p&gt;&lt;xref id="bit"/&gt;&lt;xref id="bit"/&gt;&lt;xref id="bit"/&gt;&lt;xref id="bit"/&gt;\
&lt;xref id="bit"/&gt;&lt;xref id="bit"/&gt;&lt;xref id="bit"/&gt;&lt;xref id="bit"/&gt;&lt;/p&gt;
&lt;/ref&gt;
&lt;/grammar&gt;</span></pre><div class="calloutlist">
                  <table border="0" summary="Callout list">
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.1.1"><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">首先,你要打开一个磁盘上的文件。这会提供给你一个<a href="../file_handling/file_objects.html" title="6.2.&nbsp;与文件对象共事">文件对象</a></td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.1.2"><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">将文件对象传递给 <tt class="function">minidom.parse</tt>,它调用 <tt class="varname">fsock</tt><tt class="function">read</tt> 方法并从磁盘上的文件读取 <span class="acronym">XML</span> 文档。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.1.3"><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">确保处理完文件后调用 <tt class="function">close</tt> 方法。<tt class="function">minidom.parse</tt>不会替你做这件事。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.1.4"><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">在返回的 <span class="acronym">XML</span> 文档上调用 <tt class="methodname">toxml()</tt> 方法,打印出整个文档的内容。
                        </td>
                     </tr>
                  </table>
               </div>
            </div>
            <p>哦,所有这些看上去像是在浪费大量的时间。毕竟,你已经看到,<tt class="function">minidom.parse</tt> 可以只接收文件名,并自动执行所有打开文件和关闭无用文件的行为。不错,如果你知道正要解析的是一个本地文件,你可以传递文件名而且 <tt class="function">minidom.parse</tt> 可以足够聪明地做正确的事情 (<span class="trademark">Do The Right Thing</span><sup>[<a name="d0e25377" href="#ftn.d0e25377">10</a>]</sup>),这一切都不会有问题。但是请注意,使用类文件,会使分析直接从 Internet 上来的 <span class="acronym">XML</span> 文档变得多么相似和容易!
            </p>
            <div class="example"><a name="kgp.openanything.urllib"></a><h3 class="title">&nbsp;10.2.&nbsp;解析来自 <span class="acronym">URL</span><span class="acronym">XML</span></h3><pre class="screen">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class='pykeyword'>import</span> urllib</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">usock = urllib.urlopen(<span class='pystring'>'http://slashdot.org/slashdot.rdf'</span>)</span> <a name="kgp.openanything.2.1"></a><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">xmldoc = minidom.parse(usock)</span>                              <a name="kgp.openanything.2.2"></a><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">usock.close()</span>                                              <a name="kgp.openanything.2.3"></a><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class='pykeyword'>print</span> xmldoc.toxml()</span>                                       <a name="kgp.openanything.2.4"></a><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12">
<span class="computeroutput">&lt;?xml version="1.0" ?&gt;
&lt;rdf:RDF xmlns="http://my.netscape.com/rdf/simple/0.9/"
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;

&lt;channel&gt;
&lt;title&gt;Slashdot&lt;/title&gt;
&lt;link&gt;http://slashdot.org/&lt;/link&gt;
&lt;description&gt;News for nerds, stuff that matters&lt;/description&gt;
&lt;/channel&gt;

&lt;image&gt;
&lt;title&gt;Slashdot&lt;/title&gt;
&lt;url&gt;http://images.slashdot.org/topics/topicslashdot.gif&lt;/url&gt;
&lt;link&gt;http://slashdot.org/&lt;/link&gt;
&lt;/image&gt;

&lt;item&gt;
&lt;title&gt;To HDTV or Not to HDTV?&lt;/title&gt;
&lt;link&gt;http://slashdot.org/article.pl?sid=01/12/28/0421241&lt;/link&gt;
&lt;/item&gt;

[...snip...]</span></pre><div class="calloutlist">
                  <table border="0" summary="Callout list">
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.2.1"><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">正如在<a href="../html_processing/extracting_data.html#dialect.extract.urllib" title="例&nbsp;8.5.&nbsp;urllib 介绍">前一章</a>中所看到的,<tt class="function">urlopen</tt> 接收一个 web 页面的 <span class="acronym">URL</span> 作为参数并返回一个类文件对象。最重要的是,这个对象有一个 <tt class="function">read</tt> 方法,它可以返回 web 页面的 <span class="acronym">HTML</span> 源代码。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.2.2"><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">现在把类文件对象传递给 <tt class="function">minidom.parse</tt>,它顺从地调用对象的 <tt class="function">read</tt> 方法并解析 <tt class="function">read</tt> 方法返回的 <span class="acronym">XML</span> 数据。这与 <span class="acronym">XML</span> 数据现在直接来源于 web 页面的事实毫不相干。<tt class="function">minidom.parse</tt> 并不知道 web 页面,它也不关心 web 页面;它只知道类文件对象。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.2.3"><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">到这里已经处理完毕了,确保将 <tt class="function">urlopen</tt> 提供给你的类文件对象关闭。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.2.4"><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">顺便提一句,这个 <span class="acronym">URL</span> 是真实的,它真的是一个 <span class="acronym">XML</span>。它是 <a href="http://slashdot.org/">Slashdot</a> 站点 (一个技术新闻和随笔站点) 上当前新闻提要的 <span class="acronym">XML</span> 表示。
                        </td>
                     </tr>
                  </table>
               </div>
            </div>
            <div class="example"><a name="d0e25490"></a><h3 class="title">&nbsp;10.3.&nbsp;解析字符串 <span class="acronym">XML</span> (容易但不灵活的方式)
               </h3><pre class="screen">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">contents = <span class='pystring'>"&lt;grammar&gt;&lt;ref id='bit'&gt;&lt;p&gt;0&lt;/p&gt;&lt;p&gt;1&lt;/p&gt;&lt;/ref&gt;&lt;/grammar&gt;"</span></span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">xmldoc = minidom.parseString(contents)</span> <a name="kgp.openanything.3.1"></a><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class='pykeyword'>print</span> xmldoc.toxml()</span>
<span class="computeroutput">&lt;?xml version="1.0" ?&gt;
&lt;grammar&gt;&lt;ref id="bit"&gt;&lt;p&gt;0&lt;/p&gt;&lt;p&gt;1&lt;/p&gt;&lt;/ref&gt;&lt;/grammar&gt;</span></pre><div class="calloutlist">
                  <table border="0" summary="Callout list">
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.3.1"><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left"><tt class="filename">minidom</tt> 有一个方法,<tt class="function">parseString</tt>,它接收一个字符串形式的完整 <span class="acronym">XML</span> 文档作为参数并解析这个参数。如果你已经将整个 <span class="acronym">XML</span> 文档放入一个字符串,你可以使用它代替 <tt class="function">minidom.parse</tt></td>
                     </tr>
                  </table>
               </div>
            </div>
            <p>好吧,所以你可以使用 <tt class="function">minidom.parse</tt> 函数来解析本地文件和远端 <span class="acronym">URL</span>,但对于解析字符串,你使用……另一个函数。这就是说,如果你要从文件、<span class="acronym">URL</span> 或者字符串接收输入,就需要特别的逻辑来判断参数是否是字符串,然后调用 <tt class="function">parseString</tt>。多不让人满意。
            </p>
            <p>如果有一个方法可以把字符串转换成类文件对象,那么你只要这个对象传递给 <tt class="function">minidom.parse</tt> 就可以了。事实上,有一个模块专门设计用来做这件事:<tt class="filename">StringIO</tt></p>
            <div class="example"><a name="kgp.openanything.stringio.example"></a><h3 class="title">&nbsp;10.4.&nbsp;<tt class="filename">StringIO</tt> 介绍
               </h3><pre class="screen">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">contents = <span class='pystring'>"&lt;grammar&gt;&lt;ref id='bit'&gt;&lt;p&gt;0&lt;/p&gt;&lt;p&gt;1&lt;/p&gt;&lt;/ref&gt;&lt;/grammar&gt;"</span></span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class='pykeyword'>import</span> StringIO</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">ssock = StringIO.StringIO(contents)</span>   <a name="kgp.openanything.4.1"></a><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">ssock.read()</span>                          <a name="kgp.openanything.4.2"></a><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12">
<span class="computeroutput">"&lt;grammar&gt;&lt;ref id='bit'&gt;&lt;p&gt;0&lt;/p&gt;&lt;p&gt;1&lt;/p&gt;&lt;/ref&gt;&lt;/grammar&gt;"</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">ssock.read()</span>                          <a name="kgp.openanything.4.3"></a><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12">
<span class="computeroutput">''</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">ssock.seek(0)</span>                         <a name="kgp.openanything.4.4"></a><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">ssock.read(15)</span>                        <a name="kgp.openanything.4.5"></a><img src="../images/callouts/5.png" alt="5" border="0" width="12" height="12">
<span class="computeroutput">'&lt;grammar&gt;&lt;ref i'</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">ssock.read(15)</span>
<span class="computeroutput">"d='bit'&gt;&lt;p&gt;0&lt;/p"</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">ssock.read()</span>
<span class="computeroutput">'&gt;&lt;p&gt;1&lt;/p&gt;&lt;/ref&gt;&lt;/grammar&gt;'</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">ssock.close()</span>                         <a name="kgp.openanything.4.6"></a><img src="../images/callouts/6.png" alt="6" border="0" width="12" height="12"></pre><div class="calloutlist">
                  <table border="0" summary="Callout list">
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.4.1"><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left"><tt class="filename">StringIO</tt> 模块只包含了一个类,也叫 <tt class="filename">StringIO</tt>,它允许你将一个字符串转换为一个类文件对象。 <tt class="filename">StringIO</tt> 类在创建实例时接收字符串作为参数。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.4.2"><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left"> 现在你有了一个类文件对象,你可用它做类文件的所有事情。比如 <tt class="function">read</tt> 可以返回原始字符串。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.4.3"><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">再次调用 <tt class="function">read</tt> 返回空字符串。真实文件对象的工作方式也是这样的;一旦你读取了整个文件,如果不显式定位到文件的开始位置,就不可能读取到任何其他数据。<tt class="classname">StringIO</tt> 对象以相同的方式进行工作。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.4.4"><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">使用 <tt class="classname">StringIO</tt> 对象的 <tt class="function">seek</tt> 方法,你可以显式地定位到字符串的开始位置,就像在文件中定位一样。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.4.5"><img src="../images/callouts/5.png" alt="5" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">将一个 <tt class="varname">size</tt> 参数传递给 <tt class="function">read</tt> 方法,你还可以以块的形式读取字符串。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.4.6"><img src="../images/callouts/6.png" alt="6" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">任何时候,<tt class="function">read</tt> 都将返回字符串的未读部分。所有这些严格地按文件对象的方式工作;这就是术语<span class="emphasis"><em>类文件对象</em></span> 的来历。
                        </td>
                     </tr>
                  </table>
               </div>
            </div>
            <div class="example"><a name="d0e25694"></a><h3 class="title">&nbsp;10.5.&nbsp;解析字符串 <span class="acronym">XML</span> (类文件对象方式)
               </h3><pre class="screen">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">contents = <span class='pystring'>"&lt;grammar&gt;&lt;ref id='bit'&gt;&lt;p&gt;0&lt;/p&gt;&lt;p&gt;1&lt;/p&gt;&lt;/ref&gt;&lt;/grammar&gt;"</span></span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">ssock = StringIO.StringIO(contents)</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">xmldoc = minidom.parse(ssock)</span> <a name="kgp.openanything.5.1"></a><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">ssock.close()</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class='pykeyword'>print</span> xmldoc.toxml()</span>
<span class="computeroutput">&lt;?xml version="1.0" ?&gt;
&lt;grammar&gt;&lt;ref id="bit"&gt;&lt;p&gt;0&lt;/p&gt;&lt;p&gt;1&lt;/p&gt;&lt;/ref&gt;&lt;/grammar&gt;</span></pre><div class="calloutlist">
                  <table border="0" summary="Callout list">
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.5.1"><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">现在你可以把类文件对象 (实际是一个 <tt class="classname">StringIO</tt>) 传递给 <tt class="function">minidom.parse</tt>,它将调用对象的 <tt class="function">read</tt> 方法并高兴地开始解析,绝不会知道它的输入源自一个硬编码的字符串。
                        </td>
                     </tr>
                  </table>
               </div>
            </div>
            <p>那么现在你知道了如何使用同一个函数,<tt class="function">minidom.parse</tt>,来解析一个保存在 web 页面上、本地文件中或硬编码字符串中的 <span class="acronym">XML</span> 文档。对于一个 web 页面,使用 <tt class="function">urlopen</tt> 得到类文件对象;对于本地文件,使用 <tt class="function">open</tt>;对于字符串,使用 <tt class="classname">StringIO</tt>。现在让我们进一步并归纳一下<span class="emphasis"><em>这些</em></span> 不同。
            </p>
            <div class="example"><a name="kgp.openanything.example"></a><h3 class="title">&nbsp;10.6.&nbsp;<tt class="function">openAnything</tt></h3><pre class="programlisting"><span class='pykeyword'>
def</span> openAnything(source):                  <a name="kgp.openanything.6.1"></a><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12">
    <span class='pycomment'># try to open with urllib (if source is http, ftp, or file URL)</span>
    <span class='pykeyword'>import</span> urllib                         
    <span class='pykeyword'>try</span>:                                  
        <span class='pykeyword'>return</span> urllib.urlopen(source)      <a name="kgp.openanything.6.2"></a><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12">
    <span class='pykeyword'>except</span> (IOError, OSError):            
        <span class='pykeyword'>pass</span>                              

    <span class='pycomment'># try to open with native open function (if source is pathname)</span>
    <span class='pykeyword'>try</span>:                                  
        <span class='pykeyword'>return</span> open(source)                <a name="kgp.openanything.6.3"></a><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12">
    <span class='pykeyword'>except</span> (IOError, OSError):            
        <span class='pykeyword'>pass</span>                              

    <span class='pycomment'># treat source as string</span>
    <span class='pykeyword'>import</span> StringIO                       
    <span class='pykeyword'>return</span> StringIO.StringIO(str(source))  <a name="kgp.openanything.6.4"></a><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12"></pre><div class="calloutlist">
                  <table border="0" summary="Callout list">
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.6.1"><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left"><tt class="function">openAnything</tt> 函数接受单个参数,<tt class="varname">source</tt>,并返回类文件对象。<tt class="varname">source</tt> 是某种类型的字符串;它可能是一个 <span class="acronym">URL</span> (例如 <tt class="literal">'http://slashdot.org/slashdot.rdf'</tt>),一个本地文件的完整或者部分路径名 (例如 <tt class="literal">'binary.xml'</tt>),或者是一个包含了待解析 <span class="acronym">XML</span> 数据的字符串。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.6.2"><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">首先,检查 <tt class="varname">source</tt> 是否是一个 <span class="acronym">URL</span>。这里通过强制方式进行:尝试把它当作一个 <span class="acronym">URL</span> 打开并静静地忽略打开非 <span class="acronym">URL</span> 引起的错误。这样做非常好,因为如果 <tt class="filename">urllib</tt> 将来支持更多的 <span class="acronym">URL</span> 类型,不用重新编码就可以支持它们。如果 <tt class="filename">urllib</tt> 能够打开 <tt class="varname">source</tt>,那么 <tt class="literal">return</tt> 可以立刻把你踢出函数,下面的 <tt class="literal">try</tt> 语句将不会执行。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.6.3"><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">另一方面,如果 <tt class="filename">urllib</tt> 向你呼喊并告诉你 <tt class="varname">source</tt> 不是一个有效的 <span class="acronym">URL</span>,你假设它是一个磁盘文件的路径并尝试打开它。再一次,你不用做任何特别的事来检查 <tt class="varname">source</tt> 是否是一个有效的文件名 (在不同的平台上,判断文件名有效性的规则变化很大,因此不管怎样做都可能会判断错)。反而,只要盲目地打开文件并静静地捕获任何错误就可以了。
                        </td>
                     </tr>
                     <tr>
                        <td width="12" valign="top" align="left"><a href="#kgp.openanything.6.4"><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12"></a> 
                        </td>
                        <td valign="top" align="left">到这里,你需要假设 <tt class="varname">source</tt> 是一个其中有硬编码数据的字符串 (因为没有别的可以判断的了),所以你可以使用 <tt class="classname">StringIO</tt> 从中创建一个类文件对象并将它返回。(实际上,由于使用了 <tt class="function">str</tt> 函数,所以 <tt class="varname">source</tt> 没有必要一定是字符串;它可以是任何对象,你可以使用它的字符串表示形式,只要定义了它的 <tt class="function">__str__</tt> <a href="../object_oriented_framework/special_class_methods2.html" title="5.7.&nbsp;高级专用类方法">专用方法</a>。)
                        </td>
                     </tr>
                  </table>
               </div>
            </div>
            <p>现在你可以使用这个 <tt class="function">openAnything</tt> 函数联合 <tt class="function">minidom.parse</tt> 构造一个函数,接收一个指向 <span class="acronym">XML</span> 文档的 <tt class="varname">source</tt>,而且无需知道这个 <tt class="varname">source</tt> 的含义 (可以是一个 <span class="acronym">URL</span> 或是一个本地文件名,或是一个硬编码 <span class="acronym">XML</span> 文档的字符串形式),然后解析它。
            </p>
            <div class="example"><a name="d0e25893"></a><h3 class="title">&nbsp;10.7.&nbsp;<tt class="filename">kgp.py</tt> 中使用 <tt class="function">openAnything</tt></h3><pre class="programlisting"><span class='pykeyword'>
class</span> KantGenerator:
    <span class='pykeyword'>def</span><span class='pyclass'> _load</span>(self, source):
        sock = toolbox.openAnything(source)
        xmldoc = minidom.parse(sock).documentElement
        sock.close()
        <span class='pykeyword'>return</span> xmldoc</pre></div>
         </div>
         <div class="footnotes">
            <h3 class="footnotetitle">Footnotes</h3>
            <div class="footnote">
               <p><sup>[<a name="ftn.d0e25377" href="#d0e25377">10</a>] </sup>这是一部著名的电影。――译注
               </p>
            </div>
         </div>
      </div>
      <table class="Footer" width="100%" border="0" cellpadding="0" cellspacing="0" summary="">
         <tr>
            <td width="35%" align="left"><br><a class="NavigationArrow" href="../xml_processing/summary.html">&lt;&lt;&nbsp;Segue </a></td>
            <td width="30%" align="center"><br>&nbsp;<span class="divider">|</span>&nbsp;<span class="thispage">1</span> <span class="divider">|</span> <a href="stdin_stdout_stderr.html" title="10.2.&nbsp;标准输入、输出和错误">2</a> <span class="divider">|</span> <a href="caching.html" title="10.3.&nbsp;查询缓冲节点">3</a> <span class="divider">|</span> <a href="child_nodes.html" title="10.4.&nbsp;查找节点的直接子节点">4</a> <span class="divider">|</span> <a href="handlers_by_node_type.html" title="10.5.&nbsp;根据节点类型创建不同的处理器">5</a> <span class="divider">|</span> <a href="command_line_arguments.html" title="10.6.&nbsp;处理命令行参数">6</a> <span class="divider">|</span> <a href="all_together.html" title="10.7.&nbsp;全部放在一起">7</a> <span class="divider">|</span> <a href="summary.html" title="10.8.&nbsp;小结">8</a>&nbsp;<span class="divider">|</span>&nbsp;
            </td>
            <td width="35%" align="right"><br><a class="NavigationArrow" href="stdin_stdout_stderr.html">标准输入、输出和错误&nbsp;&gt;&gt;</a></td>
         </tr>
         <tr>
            <td colspan="3"><br></td>
         </tr>
      </table>
      <div class="Footer">
         <p class="copyright">Copyright © 2000, 2001, 2002, 2003, 2004 <a href="mailto:mark@diveintopython.org">Mark Pilgrim</a></p>
         <p class="copyright">Copyright © 2001, 2002, 2003, 2004, 2005, 2006, 2007 <a href="mailto:python-cn@googlegroups.com">CPyUG (邮件列表)</a></p>
      </div>
   </body>
</html>