/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>第 10 章 脚本和流</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. Segue ">
<link rel="next" href="stdin_stdout_stderr.html" title="10.2. 标准输入、输出和错误">
</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> > <a href="../toc/index.html">Dive Into Python</a> > <span class="thispage">脚本和流</span></td>
<td id="navigation" align="right" valign="top"> <a href="../xml_processing/summary.html" title="上一页: “Segue ”"><<</a> <a href="stdin_stdout_stderr.html" title="下一页: “标准输入、输出和错误”">>></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: </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>第 10 章 脚本和流
</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. 抽象输入源
</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. 与文件对象共事">从真实文件读取数据</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">例 10.1. 从文件中解析 <span class="acronym">XML</span></h3><pre class="screen">
<tt class="prompt">>>> </tt><span class="userinput"><span class='pykeyword'>from</span> xml.dom <span class='pykeyword'>import</span> minidom</span>
<tt class="prompt">>>> </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">>>> </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">>>> </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">>>> </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"><?xml version="1.0" ?>
<grammar>
<ref id="bit">
<p>0</p>
<p>1</p>
</ref>
<ref id="byte">
<p><xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/>\
<xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/></p>
</ref>
</grammar></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. 与文件对象共事">文件对象</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">例 10.2. 解析来自 <span class="acronym">URL</span> 的 <span class="acronym">XML</span></h3><pre class="screen">
<tt class="prompt">>>> </tt><span class="userinput"><span class='pykeyword'>import</span> urllib</span>
<tt class="prompt">>>> </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">>>> </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">>>> </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">>>> </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"><?xml version="1.0" ?>
<rdf:RDF xmlns="http://my.netscape.com/rdf/simple/0.9/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<channel>
<title>Slashdot</title>
<link>http://slashdot.org/</link>
<description>News for nerds, stuff that matters</description>
</channel>
<image>
<title>Slashdot</title>
<url>http://images.slashdot.org/topics/topicslashdot.gif</url>
<link>http://slashdot.org/</link>
</image>
<item>
<title>To HDTV or Not to HDTV?</title>
<link>http://slashdot.org/article.pl?sid=01/12/28/0421241</link>
</item>
[...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="例 8.5. 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">例 10.3. 解析字符串 <span class="acronym">XML</span> (容易但不灵活的方式)
</h3><pre class="screen">
<tt class="prompt">>>> </tt><span class="userinput">contents = <span class='pystring'>"<grammar><ref id='bit'><p>0</p><p>1</p></ref></grammar>"</span></span>
<tt class="prompt">>>> </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">>>> </tt><span class="userinput"><span class='pykeyword'>print</span> xmldoc.toxml()</span>
<span class="computeroutput"><?xml version="1.0" ?>
<grammar><ref id="bit"><p>0</p><p>1</p></ref></grammar></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">例 10.4. <tt class="filename">StringIO</tt> 介绍
</h3><pre class="screen">
<tt class="prompt">>>> </tt><span class="userinput">contents = <span class='pystring'>"<grammar><ref id='bit'><p>0</p><p>1</p></ref></grammar>"</span></span>
<tt class="prompt">>>> </tt><span class="userinput"><span class='pykeyword'>import</span> StringIO</span>
<tt class="prompt">>>> </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">>>> </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">"<grammar><ref id='bit'><p>0</p><p>1</p></ref></grammar>"</span>
<tt class="prompt">>>> </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">>>> </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">>>> </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">'<grammar><ref i'</span>
<tt class="prompt">>>> </tt><span class="userinput">ssock.read(15)</span>
<span class="computeroutput">"d='bit'><p>0</p"</span>
<tt class="prompt">>>> </tt><span class="userinput">ssock.read()</span>
<span class="computeroutput">'><p>1</p></ref></grammar>'</span>
<tt class="prompt">>>> </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">例 10.5. 解析字符串 <span class="acronym">XML</span> (类文件对象方式)
</h3><pre class="screen">
<tt class="prompt">>>> </tt><span class="userinput">contents = <span class='pystring'>"<grammar><ref id='bit'><p>0</p><p>1</p></ref></grammar>"</span></span>
<tt class="prompt">>>> </tt><span class="userinput">ssock = StringIO.StringIO(contents)</span>
<tt class="prompt">>>> </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">>>> </tt><span class="userinput">ssock.close()</span>
<tt class="prompt">>>> </tt><span class="userinput"><span class='pykeyword'>print</span> xmldoc.toxml()</span>
<span class="computeroutput"><?xml version="1.0" ?>
<grammar><ref id="bit"><p>0</p><p>1</p></ref></grammar></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">例 10.6. <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. 高级专用类方法">专用方法</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">例 10.7. 在 <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"><< Segue </a></td>
<td width="30%" align="center"><br> <span class="divider">|</span> <span class="thispage">1</span> <span class="divider">|</span> <a href="stdin_stdout_stderr.html" title="10.2. 标准输入、输出和错误">2</a> <span class="divider">|</span> <a href="caching.html" title="10.3. 查询缓冲节点">3</a> <span class="divider">|</span> <a href="child_nodes.html" title="10.4. 查找节点的直接子节点">4</a> <span class="divider">|</span> <a href="handlers_by_node_type.html" title="10.5. 根据节点类型创建不同的处理器">5</a> <span class="divider">|</span> <a href="command_line_arguments.html" title="10.6. 处理命令行参数">6</a> <span class="divider">|</span> <a href="all_together.html" title="10.7. 全部放在一起">7</a> <span class="divider">|</span> <a href="summary.html" title="10.8. 小结">8</a> <span class="divider">|</span>
</td>
<td width="35%" align="right"><br><a class="NavigationArrow" href="stdin_stdout_stderr.html">标准输入、输出和错误 >></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>
|