python again函数_python第六天 函数 python标准库实例大全

1 1. 核心模块2 o 1.1. 介绍3 o 1.2. _ _builtin_ _ 模块4 o 1.3. exceptions 模块5 o 1.4. os 模块6 o 1.5. os.path 模块7 o 1.6. stat 模块8 o 1.7. string 模块9 o 1.8. re 模块10 o 1.9. math 模块11 o 1.10. cmath 模块12 o 1.11. operator 模块13 o 1.12. copy 模块14 o 1.13. sys 模块15 o 1.14. atexit 模块16 o 1.15. time 模块17 o 1.16. types 模块18 o 1.17. gc 模块19

20

21

22

23

24 1. 核心模块25 "Since the functions in the C runtime library are not part of the Win32

26 API, we believe the number of applications that will be affected by this27 bug to be very limited."28 - Microsoft, January 1999

29 1.1. 介绍30 Python 的标准库包括了很多的模块, 从 Python 语言自身特定的类型和声明,31 到一些只用于少数程序的不著名的模块.32 本章描述了一些基本的标准库模块. 任何大型 Python 程序都有可能直接或间33 接地使用到这类模块的大部分.34 1.1.1. 内建函数和异常35 下面的这两个模块比其他模块加在一起还要重要: 定义内建函数(例如 len,36 int, range ...)的 _ _builtin_ _ 模块, 以及定义所有内建异常的 exceptions37 模块.38 Python 在启动时导入这两个模块, 使任何程序都能够使用它们.39 1.1.2. 操作系统接口模块40 Python 有许多使用了 POSIX 标准 API 和标准 C 语言库的模块. 它们为底层41 操作系统提供了平台独立的接口.42 这类的模块包括: 提供文件和进程处理功能的 os 模块; 提供平台独立的文件43 名处理 (分拆目录名, 文件名, 后缀等)的 os.path 模块; 以及时间日期处理44 相关的 time/datetime 模块.45 [!Feather 注: datetime 为 Py2.3新增模块, 提供增强的时间处理方法 ]46 延伸一点说, 网络和线程模块同样也可以归为这一个类型. 不过 Python 并没47 有在所有的平台/版本实现这些.48 1.1.3. 类型支持模块49 标准库里有许多用于支持内建类型操作的库. string 模块实现了常用的字符串50 处理. math 模块提供了数学计算操作和常量(pi, e 都属于这类常量), cmath 模51 块为复数提供了和 math 一样的功能.52 1.1.4. 正则表达式53 re 模块为 Python 提供了正则表达式支持. 正则表达式是用于匹配字符串或特54 定子字符串的有特定语法的字符串模式.55 1.1.5. 语言支持模块56 sys 模块可以让你访问解释器相关参数,比如模块搜索路径,解释器版本号等.57 operator 模块提供了和内建操作符作用相同的函数. copy 模块允许你复制对58 象, Python 2.0新加入的 gc 模块提供了对垃圾收集的相关控制功能.59 1.2. _ _builtin_ _ 模块60 这个模块包含 Python 中使用的内建函数. 一般不用手动导入这个模块;61 Python 会帮你做好一切.62 1.2.1. 使用元组或字典中的参数调用函数63 Python 允许你实时地创建函数参数列表. 只要把所有的参数放入一个元组中,64 然后通过内建的 apply 函数调用函数. 如 Example 1-1.65 1.2.1.1. Example 1-1. 使用 apply 函数66 File: builtin-apply-example-1.py67 deffunction(a, b):68 printa, b69 apply(function, ("whither", "canada?"))70 apply(function, (1, 2 + 3))71 whither canada?72 1 5

73 要想把关键字参数传递给一个函数, 你可以将一个字典作为 apply 函数的第 3

74 个参数, 参考 Example 1-2.75 1.2.1.2. Example 1-2. 使用 apply 函数传递关键字参数76 File: builtin-apply-example-2.py77 deffunction(a, b):78 printa, b79 apply(function, ("crunchy", "frog"))80 apply(function, ("crunchy",), {"b": "frog"})81 apply(function, (), {"a": "crunchy", "b": "frog"})82 crunchy frog83 crunchy frog84 crunchy frog85 apply 函数的一个常见用法是把构造函数参数从子类传递到基类, 尤其是构造86 函数需要接受很多参数的时候. 如 Example 1-3所示.87 1.2.1.3. Example 1-3. 使用 apply 函数调用基类的构造函数88 File: builtin-apply-example-3.py89 classRectangle:90 def _ _init_ _(self, color="white", width=10, height=10):91 print "create a", color, self, "sized", width, "x", height92 classRoundedRectangle(Rectangle):93 def _ _init_ _(self, **kw):94 apply(Rectangle._ _init_ _, (self,), kw)95 rect = Rectangle(color="green", height=

96 100, width=100) rect= RoundedRectangle(color=

97 "blue",98 height = 20)< /FONT> <

99 FONT face= 宋体>

100 create a green sized 100 x 100

101 create a blue sized 10 x 20

102 Python 2.0提供了另个方法来做相同的事. 你只需要使用一个传统的函数调103 用 , 使用 * 来标记元组, **来标记字典.104 下面两个语句是等价的:105 result = function(*args, **kwargs)106 result =

107 apply(function, args, kwargs) < /FONT108 >

109 1.2.2. 加载和重载模块110 如果你写过较庞大的 Python 程序, 那么你就应该知道 import语句是用来导111 入外部模块的 (当然也可以使用 from-import版本). 不过你可能不知道112 import其实是靠调用内建函数 _ _import_ _ 来工作的.113 通过这个戏法你可以动态地调用函数. 当你只知道模块名称(字符串)的时候,114 这将很方便. Example 1-4 展示了这种用法, 动态地导入所有以 "-plugin"结115 尾的模块.116 1.2.2.1. Example 1-4. 使用 _ _import_ _ 函数加载模块117 File: builtin-import-example-1.py118 importglob, os119 modules =[]120 for module_file in glob.glob("*-plugin.py"):121 try:122 module_name, ext =

123 os.path.splitext(os.path.basename(module_file))124 module =_ _import_ _(module_name)125 modules.append(module)126 exceptImportError:127 pass #ignore broken modules

128 #say hello to all modules

129 for module inmodules:130 module.hello()131 example-plugin says hello132 注意这个 plug-in 模块文件名中有个 "-"(hyphens). 这意味着你不能使用普133 通的 import 命令, 因为 Python 的辨识符不允许有 "-".134 Example 1-5 展示了 Example 1-4 中使用的 plug-in.135 1.2.2.2. Example 1-5. Plug-in例子136 File: example-plugin.py137 defhello():138 print "example-plugin says hello"

139 Example 1-6展示了如何根据给定模块名和函数名获得想要的函数对象.140 1.2.2.3. Example 1-6. 使用 _ _import_ _ 函数获得特定函数141 File: builtin-import-example-2.py142 defgetfunctionbyname(module_name, function_name):143 module =_ _import_ _(module_name)144 returngetattr(module, function_name)145 print repr(getfunctionbyname("dumbdbm", "open"))146

147 你也可以使用这个函数实现延迟化的模块导入 (lazy module loading). 例如在148 Example 1-7中的 string 模块只在第一次使用的时候导入.149 1.2.2.4. Example 1-7. 使用 _ _import_ _ 函数实现 延迟导入150 File: builtin-import-example-3.py151 classLazyImport:152 def_ _init_ _(self, module_name):153 self.module_name =module_name154 self.module =None155 def_ _getattr_ _(self, name):156 if self.module isNone:157 self.module =_ _import_ _(self.module_name)158 returngetattr(self.module, name)159 string = LazyImport("string")160 printstring.lowercase161 abcdefghijklmnopqrstuvwxyz162 Python 也提供了重新加载已加载模块的基本支持. [Example 1-8 #eg-1-8 会加

163 载 3次 hello.py 文件.164 1.2.2.5. Example 1-8. 使用 reload 函数165 File: builtin-reload-example-1.py166 importhello167 reload(hello)168 reload(hello)169 hello again, andwelcome to the show170 hello again, andwelcome to the show171 hello again, andwelcome to the show172 reload 直接接受模块作为参数.173 [!Feather 注: ^原句无法理解, 稍后讨论.]174 注意,当你重加载模块时, 它会被重新编译, 新的模块会代替模块字典里的老模175 块. 但是, 已经用原模块里的类建立的实例仍然使用的是老模块(不会被更新).176 同样地, 使用 from-import直接创建的到模块内容的引用也是不会被更新的.177 1.2.3. 关于名称空间178 dir 返回由给定模块, 类, 实例, 或其他类型的所有成员组成的列表. 这可能179 在交互式 Python 解释器下很有用, 也可以用在其他地方. Example 1-9展示了180 dir 函数的用法.181 1.2.3.1. Example 1-9. 使用 dir 函数182 File: builtin-dir-example-1.py183 defdump(value):184 print value, "=>", dir(value)185 importsys186 dump(0)187 dump(1.0)188 dump(0.0j) #complex number

189 dump([]) #list

190 dump({}) #dictionary

191 dump("string")192 dump(len) #function

193 dump(sys) #module

194 0 =>[]195 1.0 =>[]196 0j => ['conjugate', 'imag', 'real']197 [] => ['append', 'count', 'extend', 'index', 'insert',198 'pop', 'remove', 'reverse', 'sort']199 {} => ['clear', 'copy',200 'get', 'has_key',201 'items', 'keys', 'update', 'values']202 string =

203 > [] = > ['_ _doc_ _', '_

205 _name_ _','_206 _self_ _']

207 =

208 > ['_ _doc_ _', '_ _name_ _',209 '_ _stderr_ _', '_ _stdin_ _', '_ _stdout_ _', 'argv',210 'builtin_module_names', 'copyright', 'dllhandle',211 'exc_info', 'exc_type', 'exec_prefix', 'executable',212 ...213 在例子 Example 1-10中定义的 getmember 函数返回给定类定义的所有类级别214 的属性和方法.215 1.2.3.2. Example 1-10. 使用 dir 函数查找类的所有成员216 File: builtin-dir-example-2.py217 classA:218 defa(self):219 pass

220 defb(self):221 pass

222 classB(A):223 defc(self):224 pass

225 defd(self):226 pass

227 def getmembers(klass, members=None):228 #get a list of all class members, ordered by class

229 if members isNone:230 members =[]231 for k inklass._ _bases_ _:232 getmembers(k, members)233 for m indir(klass):234 if m not inmembers:235 members.append(m)236 returnmembers237 printgetmembers(A)238 printgetmembers(B)239 printgetmembers(IOError)240 <

241 FONT face=

242 宋体243 >

244 ['_ _doc_ _', '_ _module_ _', 'a', 'b']245 ['_ _doc_ _', '_ _module_ _', 'a', 'b', 'c', 'd']246 ['_ _doc_ _', '_ _getitem_ _', '_ _init_ _', '_ _module_ _', '_ _str_

247 _']

248 getmembers 函数返回了一个有序列表. 成员在列表中名称出现的越早, 它所处249 的类层次就越高. 如果无所谓顺序的话, 你可以使用字典代替列表.250 [!Feather 注: 字典是无序的, 而列表和元组是有序的, 网上有关于有序字典251 的讨论]252 vars 函数与此相似, 它返回的是包含每个成员当前值的字典. 如果你使用不带253 参数的 vars , 它将返回当前局部名称空间的可见元素(同 locals() 函数 ).254 如 Example 1-11所表示.255 1.2.3.3. Example 1-11. 使用 vars 函数256 File: builtin-vars-example-1.py257 book = "library2"

258 pages = 250

259 scripts = 350

260 print "the %(book)s book contains more than %(scripts)s scripts" %vars()261 the library book contains more than 350scripts262 1.2.4. 检查对象类型263 Python 是一种动态类型语言, 这意味着给一个定变量名可以在不同的场合绑定264 到不同的类型上. 在接下面例子中, 同样的函数分别被整数, 浮点数, 以及一265 个字符串调用:266 deffunction(value):267 printvalue268 function(1)269 function(1.0)270 function("one")271 type 函数 (如 Example 1-12所示) 允许你检查一个变量的类型. 这个函数会272 返回一个 type descriptor (类型描述符) , 它对于 Python 解释器提供的每个273 类型都是不同的.274 1.2.4.1. Example 1-12. 使用 type 函数275 File: builtin-type-example-1.py276 defdump(value):277 printtype(value), value278 dump(1)279 dump(1.0)280 dump("one")281 1

282 1.0

283 one284 每个类型都有一个对应的类型对象, 所以你可以使用 is操作符 (对象身份?)285 来检查类型. (如 Example 1-13所示).286 1.2.4.2. Example 1-13. 对文件名和文件对象使用 type 函数287 File: builtin-type-example-2.py288 defload(file):289 if isinstance(file, type("")):290 file = open(file, "rb")291 returnfile.read()292 print len(load("samples/sample.jpg")), "bytes"

293 print len(load(open("samples/sample.jpg", "rb"))), "bytes"

294 4672bytes295 4672bytes296 callable 函数, 如 Example 1-14所示, 可以检查一个对象是否是可调用的297 (无论是直接调用或是通过 apply ). 对于函数, 方法, lambda函式, 类, 以及298 实现了 _ _call_ _ 方法的类实例, 它都返回 True.299 1.2.4.3. Example 1-14. 使用 callable 函数300 File: builtin-callable-example-1.py301 defdump(function):302 ifcallable(function):303 print function, "is callable"

304 else:305 print function, "is *not* callable"

306 classA:307 defmethod(self, value):308 returnvalue309 classB(A):310 def_ _call_ _(self, value):311 returnvalue312 a =A()313 b =B()314 dump(0) #simple objects

315 dump("string")316 dump(callable)317 dump(dump) #function

318 dump(A) #classes

319 dump(B)320 dump(B.method)321 dump(a) #instances

322 dump(b)323 dump(b.method)324 <

325 FONT326 face =

327 宋体328 >

329 0 is *not*callable330 string is *not*callable331 iscallable332 iscallable333 A iscallable334 B iscallable335 iscallable336 is *not*callable337 iscallable338 iscallable339 注意类对象 (A 和 B) 都是可调用的; 如果调用它们, 就产生新的对象(类实340 例). 但是 A 类的实例不可调用, 因为它的类没有实现 _ _call_ _ 方法.341 你可以在 operator 模块中找到检查对象是否为某一内建类型(数字, 序列, 或342 者字典等) 的函数. 但是, 因为创建一个类很简单(比如实现基本序列方法的343 类), 所以对这些类型使用显式的类型判断并不是好主意.344 在处理类和实例的时候会复杂些. Python 不会把类作为本质上的类型对待; 相345 反地, 所有的类都属于一个特殊的类类型(special classtype), 所有的类实例346 属于一个特殊的实例类型(special instance type).347 这意味着你不能使用 type 函数来测试一个实例是否属于一个给定的类; 所有348 的实例都是同样的类型! 为了解决这个问题, 你可以使用 isinstance 函数,它349 会检查一个对象是不是给定类(或其子类)的实例. Example 1-15展示了350 isinstance 函数的使用.351 1.2.4.4. Example 1-15. 使用 isinstance 函数352 File: builtin-isinstance-example-1.py353 classA:354 pass

355 classB:356 pass

357 classC(A):358 pass

359 classD(A, B):360 pass

361 defdump(object):362 print object, "=>",363 ifisinstance(object, A):364 print "A",365 ifisinstance(object, B):366 print "B",367 ifisinstance(object, C):368 print "C",369 ifisinstance(object, D):370 print "D",371 print

372 a =A()373 b =

374 B() c=

375 C()376 d =

377 D()378 dump(a) dump(b)379 dump(c)380 dump(d)381 dump(0)382 dump("string")< /FONT383 >

385 宋体386 >

387 =>A388 =>B389 =

390 >A C391 = >

392 A B D 0 = >

393 string =

394 >

395 issubclass 函数与此相似, 它用于检查一个类对象是否与给定类相同, 或者是396 给定类的子类. 如 Example 1-16所示.397 注意, isinstance 可以接受任何对象作为参数, 而 issubclass 函数在接受非398 类对象参数时会引发 TypeError 异常.399 1.2.4.5. Example 1-16. 使用 issubclass 函数400 File: builtin-issubclass-example-1.py401 classA:402 pass

403 classB:404 pass

405 classC(A):406 pass

407 classD(A, B):408 pass

409 defdump(object):410 print object, "=>",411 ifissubclass(object, A):412 print "A",413 ifissubclass(object, B):414 print "B",415 ifissubclass(object, C):416 print "C",417 ifissubclass(object, D):418 print "D",419 print

420 dump(A)421 dump(B)422 dump(C)423 dump(D)424 dump(0)425 dump("string")426 A =>A427 B =>B428 C =>A C429 D = >

430 A B D431 0 =

432 >

433 Traceback (innermost last):434 File "builtin-issubclass-example-1.py", line 29, in?435 File "builtin-issubclass-example-1.py", line 15, indump436 TypeError: arguments must be classes437 1.2.5. 计算 Python 表达式438 Python 提供了在程序中与解释器交互的多种方法. 例如 eval 函数将一个字符439 串作为 Python 表达式求值. 你可以传递一串文本, 简单的表达式, 或者使用440 内建 Python 函数. 如 Example 1-17所示.441 1.2.5.1. Example 1-17. 使用 eval 函数442 File: builtin-eval-example-1.py443 defdump(expression):444 result =eval(expression)445 print expression, "=>", result, type(result)446 dump("1")447 dump("1.0")448 dump("'string'")449 dump("1.0 + 2.0")450 dump("'*' * 10")451 dump("len('world')")452 <

453 FONT454 face =

455 宋体>

456 1 => 1

457 1.0 => 1.0

458 'string' = >string459 1.0 +

460 2.0 = >

461 3.0 '*' * 10=

462 > ********** len('world')=

463 > 5

464 如果你不确定字符串来源的安全性, 那么你在使用 eval 的时候会遇到些麻烦.465 例如, 某个用户可能会使用 _ _import_ _ 函数加载 os 模块, 然后从硬盘删除466 文件 (如 Example 1-18所示).467 1.2.5.2. Example 1-18. 使用 eval 函数执行任意命令468 File: builtin-eval-example-2.py469 print eval("_ _import_ _('os').getcwd()")470 print eval("_ _import_ _('os').remove('file')")471 /home/fredrik/librarybook Traceback (innermost472 last): File "builtin-eval-example-2", line 2, in

473 ? File"", line 0, in?474 os.error: (2, 'No such file or directory')475 这里我们得到了一个 os.error 异常, 这说明 Python 事实上在尝试删除文件!476 幸运地是, 这个问题很容易解决. 你可以给 eval 函数传递第 2个参数, 一个477 定义了该表达式求值时名称空间的字典. 我们测试下, 给函数传递个空字典:478 >>> print eval("_ _import_

479 _('os').remove('file')", {}) Traceback

480 (innermost last):File "", line 1, in

481 ? File"", line 0, in?482 os.error: (2, 'No such file or directory')483 呃.... 我们还是得到了个 os.error 异常.484 这是因为 Python 在求值前会检查这个字典, 如果没有发现名称为 _485 _builtins_ _ 的变量(复数形式), 它就会添加一个:486 >>> namespace = {} >>>

487 print eval("_ _import_ _('os').remove('file')", namespace)488 Traceback (innermost last):489 File "",line 1, in? File490 "", line0, in ? os.error: (2,491 'No such file or directory') >>>namespace.keys()492 ['_

493 _builtins_ _'] <

494 /FONT >

495 如果你打印这个 namespace 的内容, 你会发现里边有所有的内建函数.496 [!Feather 注: 如果我RP 不错的话, 添加的这个_ _builtins_ _就是当前的_497 _builtins_ _]498 我们注意到了如果这个变量存在, Python 就不会去添加默认的, 那么我们的解499 决方法也来了, 为传递的字典参数加入一个 _ _builtins_ _ 项即可. 如500 Example 1-19所示.501 1.2.5.3. Example 1-19. 安全地使用 eval 函数求值502 File: builtin-eval-example-3.py503 print eval("_ _import_ _('os').getcwd()", {})504 print eval("_ _import_ _('os').remove('file')", {"_ _builtins_ _": {}})505 /home/fredrik/librarybook Traceback (innermost506 last): File "builtin-eval-example-3.py", line 2, in

507 ? File"", line 0, in?508 NameError: _ _import_ _509 即使这样, 你仍然无法避免针对 CPU 和内存资源的攻击. (比如, 形如510 eval("'*'*1000000*2*2*2*2*2*2*2*2*2") 的语句在执行后会使你的程序耗尽511 系统资源).512 1.2.6. 编译和执行代码513 eval 函数只针对简单的表达式. 如果要处理大块的代码, 你应该使用 compile514 和 exec 函数 (如 Example 1-20所示).515 1.2.6.1. Example 1-20. 使用 compile 函数检查语法516 File: builtin-compile-example-1.py517 NAME = "script.py"

518 BODY =

519 """prnt520 'owl-stretching time'"""

521 try:522 compile(BODY,523 NAME, "exec") except

524 SyntaxError, v: print

525 "syntax error:", v, "in", NAME #526 syntax error: invalid syntax inscript.py527 < /FONT528 >

529 成功执行后, compile 函数会返回一个代码对象, 你可以使用 exec语句执行530 它, 参见 Example 1-21.531 1.2.6.2. Example 1-21. 执行已编译的代码532 File: builtin-compile-example-2.py533 BODY = """

534 print 'the ant, an introduction'535 """

536 code = compile(BODY,"

541 宋体542 >

543 ", line 0>

544 the ant, an introduction545 使用 Example 1-22中的类可以在程序执行时实时地生成代码. write 方法用于546 添加代码, indent 和 dedent 方法用于控制缩进结构. 其他部分交给类来处547 理.548 1.2.6.3. Example 1-22. 简单的代码生成工具549 File: builtin-compile-example-3.py550 importsys, string551 classCodeGeneratorBackend:552 "Simple code generator for Python"

553 def begin(self, tab="\t"):554 self.code =[]555 self.tab =tab556 self.level =0557 defend(self):558 self.code.append("") #make sure there's a newline at the end

559 return compile(string.join(self.code, "\n"), "", "exec")560 defwrite(self, string):561 self.code.append(self.tab * self.level +string)562 defindent(self):563 self.level = self.level +

564 1 #in

565 2.0 and

566 later, this can be written567 as: self.level +=

568 1 def

569 dedent(self): if

570 self.level =

571 =

572 0:573 raise SyntaxError, "internal error in

574 code generator"575 self.level =

576 self.level- 1

577 #or:

578 self.level - =

579 1

580 #581 #try

582 it out!583 c =

584 CodeGeneratorBackend()585 c.begin() c.write("for

586 i in range(5):") c.indent()

587 c.write("print 'code generation made easy!'") c.dedent() exec

588 c.end()< /FONT >

590 宋体591 >

592 code generation made easy!593 code generation made easy!594 code generation made easy!595 code generation made easy!596 code generation made easy!597 Python 还提供了 execfile 函数, 一个从文件加载代码, 编译代码, 执行代码598 的快捷方式. Example 1-23简单地展示了如何使用这个函数.599 1.2.6.4. Example 1-23. 使用 execfile 函数600 File: builtin-execfile-example-1.py601 execfile("hello.py")602 def EXECFILE(filename, locals=None, globals=None):603 exec compile(open(filename).read(), filename, "exec") inlocals,604 globals605 EXECFILE("hello.py")606 <

607 FONT face= 宋体>

608 hello again, andwelcome to the show609 hello again, andwelcome to the show610 Example 1-24 中的代码是 Example 1-23中使用的 hello.py 文件.611 1.2.6.5. Example 1-24. hello.py 脚本612 File: hello.py613 print "hello again, and welcome to the show"

614 1.2.7. 从 _ _builtin_ _ 模块重载函数615 因为 Python 在检查局部名称空间和模块名称空间前不会检查内建函数, 所以616 有时候你可能要显式地引用 _ _builtin_ _ 模块. 例如 Example 1-25重载了617 内建的 open 函数. 这时候要想使用原来的 open 函数, 就需要脚本显式地指618 明模块名称.619 1.2.7.1. Example 1-25. 显式地访问 _ _builtin_ _ 模块中的函数620 File: builtin-open-example-1.py621 def open(filename, mode="rb"):622 import_ _builtin_ _623 file =_ _builtin_ _.open(filename, mode)624 if file.read(5) not in("GIF87", "GIF89"): raise

625 IOError, "not aGIF

626 file"file.seek(0) return file

627 fp =

628 open("samples/sample.gif")629 print

630 len(fp.read()), "bytes"

631 fp =

632 open("samples/sample.jpg") print

633 len(fp.read()), "bytes"

634 < /FONT> <

635 FONT636 face=

637 宋体638 >

639 3565bytes640 Traceback (innermost last):641 File "builtin-open-example-1.py", line 12, in?642 File "builtin-open-example-1.py", line 5, inopen643 IOError: nota GIF file644 [!Feather 注: 明白这个open()函数是干什么的么? 检查一个文件是否是 GIF645 文件,646 一般如这类的图片格式都在文件开头有默认的格式.647 另外打开文件推荐使用file()而不是open() , 虽然暂时没有区别]648 1.3. exceptions 模块649 exceptions 模块提供了标准异常的层次结构. Python 启动的时候会自动导入650 这个模块, 并且将它加入到 _ _builtin_ _ 模块中. 也就是说, 一般不需要手651 动导入这个模块.652 在 1.5.2 版本时它是一个普通模块, 2.0以及以后版本成为内建模块.653 该模块定义了以下标准异常:654 • Exception 是所有异常的基类. 强烈建议(但不是必须)自定义的异常异655 常也继承这个类.656 • SystemExit(Exception) 由 sys.exit 函数引发. 如果它在最顶层没有657 被 try-except语句捕获, 那么解释器将直接关闭而不会显示任何跟踪658 返回信息.659 • StandardError(Exception) 是所有内建异常的基类(除 SystemExit660 外).661 • KeyboardInterrupt(StandardError) 在用户按下 Control-C(或其他打662 断按键)后 被引发. 如果它可能会在你使用 "捕获所有" 的 try-except

663 语句时导致奇怪的问题.664 • ImportError(StandardError) 在 Python 导入模块失败时被引发.665 • EnvironmentError 作为所有解释器环境引发异常的基类. (也就是说,666 这些异常一般不是由于程序 bug 引起).667 • IOError(EnvironmentError) 用于标记 I/O 相关错误.668 • OSError(EnvironmentError) 用于标记 os 模块引起的错误.669 • WindowsError(OSError) 用于标记 os 模块中 Windows 相关错误.670 • NameError(StandardError) 在 Python 查找全局或局部名称失败时被引671 发.672 • UnboundLocalError(NameError) , 当一个局部变量还没有赋值就被使用673 时, 会引发这个异常. 这个异常只有在2.0 及之后的版本有; 早期版本674 只会引发一个普通的 NameError .675 • AttributeError(StandardError) , 当 Python 寻找(或赋值)给一个实676 例属性, 方法, 模块功能或其它有效的命名失败时, 会引发这个异常.677 • SyntaxError(StandardError) , 当解释器在编译时遇到语法错误, 这个678 异常就被引发.679 • (2.0及以后版本) IndentationError(SyntaxError) 在遇到非法的缩进680 时被引发. 该异常只用于 2.0及以后版本, 之前版本会引发一个681 SyntaxError 异常.682 • (2.0 及以后版本) TabError(IndentationError) , 当使用 -tt 选项检683 查不一致缩进时有可能被引发. 该异常只用于 2.0及以后版本, 之前版684 本会引发一个 SyntaxError 异常.685 • TypeError(StandardError) , 当给定类型的对象不支持一个操作时被引686 发.687 • AssertionError(StandardError) 在 assert语句失败时被引发(即表达688 式为 false 时).689 • LookupError(StandardError) 作为序列或字典没有包含给定索引或键时690 所引发异常的基类.691 • IndexError(LookupError) , 当序列对象使用给定索引数索引失败时(不692 存在索引对应对象)引发该异常.693 • KeyError(LookupError) 当字典对象使用给定索引索引失败时(不存在索694 引对应对象)引发该异常.695 • ArithmeticError(StandardError) 作为数学计算相关异常的基类.696 • OverflowError(ArithmeticError) 在操作溢出时被引发(例如当一个整697 数太大, 导致不能符合给定类型).698 • ZeroDivisionError(ArithmeticError) , 当你尝试用 0 除某个数时被699 引发.700 • FloatingPointError(ArithmeticError) , 当浮点数操作失败时被引发.701 • ValueError(StandardError) , 当一个参数类型正确但值不合法时被引702 发.703 • (2.0及以后版本) UnicodeError(ValueError) , Unicode 字符串类型相704 关异常. 只使用在 2.0及以后版本.705 • RuntimeError(StandardError) , 当出现运行时问题时引发, 包括在限706 制模式下尝试访问外部内容, 未知的硬件问题等等.707 • NotImplementedError(RuntimeError) , 用于标记未实现的函数, 或无708 效的方法.709 • SystemError(StandardError) , 解释器内部错误. 该异常值会包含更多710 的细节 (经常会是一些深层次的东西, 比如 "eval_code2: NULL

711 globals") . 这本书的作者编了 5 年程序都没见过这个错误. (想必是

712 没有用 raiseSystemError ).713 • MemoryError(StandardError) , 当解释器耗尽内存时会引发该异常. 注714 意只有在底层内存分配抱怨时这个异常才会发生; 如果是在你的旧机器715 上, 这个异常发生之前系统会陷入混乱的内存交换中.716 你可以创建自己的异常类. 只需要继承内建的 Exception 类(或者它的任意一717 个合适的子类)即可, 有需要时可以再重载它的 _ _str_ _ 方法. Example 1-26

718 展示了如何使用 exceptions 模块.719 1.3.0.1. Example 1-26. 使用 exceptions 模块720 File: exceptions-example-1.py721 #python imports this module by itself, so the following

722 #line isn't really needed

723 #python 会自动导入该模块, 所以以下这行是不必要的

724 #import exceptions

725 classHTTPError(Exception):726 #indicates an HTTP protocol error

727 def_ _init_ _(self, url, errcode, errmsg):728 self.url =url729 self.errcode =errcode730 self.errmsg =

731 errmsg def_ _str_ _(self):732 return ( ""

733 %(self.url,734 self.errcode, self.errmsg)735 ) try:736 raise HTTPError("http://www.python.org/foo", 200, "Not

737 Found") except

738 HTTPError, error: print "url", "=

739 >", error.url

740 print "errcode", "=>", error.errcode741 print "errmsg", "=

742 >",

743 error.errmsg raise #744 reraise exception745 < /FONT746 >

747 <

748 FONT face=

749 宋体>

750 url => http://www.python.org/foo751 errcode => 200

752 errmsg =

753 >Not Found754 Traceback (innermost last):755 File "exceptions-example-1", line 16, in?756 HTTPError:

757 1.4. os 模块758 这个模块中的大部分函数通过对应平台相关模块实现, 比如 posix 和 nt. os759 模块会在第一次导入的时候自动加载合适的执行模块.760 1.4.1. 处理文件761 内建的 open / file 函数用于创建, 打开和编辑文件, 如 Example 1-27所示.762 而 os 模块提供了重命名和删除文件所需的函数.763 1.4.1.1. Example 1-27. 使用 os 模块重命名和删除文件764 File: os-example-3.py765 importos766 importstring767 defreplace(file, search_for, replace_with):768 #replace strings in a text file

769 back = os.path.splitext(file)[0] + ".bak"

770 temp = os.path.splitext(file)[0] + ".tmp"

771 try:772 #remove old temp file, if any

773 os.remove(temp)774 exceptos.error:775 pass

776 fi =open(file)777 fo = open(temp, "w")778 for s in

779 fi.readlines(): fo.write(string.replace(s,780 search_for, replace_with))781 fi.close() fo.close() try: #782 remove old backup file, ifany os.remove(back)783 except os.error: pass #784 rename original to backup...785 os.rename(file,786 back) #...and temporary to original os.rename(temp,

787 file)788 ##

789 try

790 it out!791 file =

792 "samples/sample.txt"

793 replace(file,794 "hello", "tjena")795 replace(file,796 "tjena", "hello")797 < /FONT798 >

799 1.4.2. 处理目录800 os 模块也包含了一些用于目录处理的函数.801 listdir 函数返回给定目录中所有文件名(包括目录名)组成的列表, 如802 Example 1-28所示. 而 Unix 和 Windows 中使用的当前目录和父目录标记(.803 和 .. )不包含在此列表中.804 1.4.2.1. Example 1-28. 使用 os 列出目录下的文件805 File: os-example-5.py806 importos807 for file in os.listdir("samples"):808 printfile809 sample.au810 sample.jpg811 sample.wav812 ...813 getcwd 和 chdir 函数分别用于获得和改变当前工作目录. 如 Example 1-29

814 所示.815 1.4.2.2. Example 1-29. 使用 os 模块改变当前工作目录816 File: os-example-4.py817 importos818 #where are we?

819 cwd =os.getcwd()820 print "1", cwd821 #go down

822 os.chdir("samples")823 print "2", os.getcwd()824 #go back up

825 os.chdir(os.pardir)826 print "3", os.getcwd()827 1 /ematter/librarybook828 2 /ematter/librarybook/samples829 3 /ematter/librarybook830 makedirs 和 removedirs 函数用于创建或删除目录层,如 Example 1-30所示.831 1.4.2.3. Example 1-30. 使用 os 模块创建/删除多个目录级832 File: os-example-6.py833 importos834 os.makedirs("test/multiple/levels")835 fp =

836 open("test/multiple/levels/file", "w") fp.write("inspector

837 praline") fp.close()

838 #839 remove the file os.remove("test/multiple/levels/file")840 #841 and all empty directories above it os.removedirs("test/multiple/levels")842 <

843 /FONT844 >

845 removedirs 函数会删除所给路径中最后一个目录下所有的空目录. 而 mkdir846 和 rmdir 函数只能处理单个目录级. 如 Example 1-31所示.847 1.4.2.4. Example 1-31. 使用 os 模块创建/删除目录848 File: os-example-7.py849 importos850 os.mkdir("test")851 os.rmdir("test")852 os.rmdir("samples") #this will fail

853 Traceback (innermost last):854 File "os-example-7", line 6, in?855 OSError: [Errno 41] Directory not empty: 'samples'

856 如果需要删除非空目录, 你可以使用 shutil 模块中的 rmtree 函数.857 1.4.3. 处理文件属性858 stat 函数可以用来获取一个存在文件的信息, 如 Example 1-32所示. 它返回859 一个类元组对象(stat_result 对象, 包含 10个元素), 依次是st_mode (权限860 模式), st_ino (inode number), st_dev (device), st_nlink (number of hard861 links), st_uid (所有者用户 ID), st_gid (所有者所在组 ID ), st_size (文862 件大小, 字节), st_atime (最近一次访问时间), st_mtime (最近修改时间),863 st_ctime (平台相关; Unix 下的最近一次元数据/metadata 修改时间, 或者864 Windows 下的创建时间) -以上项目也可作为属性访问.865 [!Feather 注: 原文为 9元元组. 另,返回对象并非元组类型,为 struct.]866 1.4.3.1. Example 1-32. 使用 os 模块获取文件属性867 File: os-example-1.py868 importos869 importtime870 file = "samples/sample.jpg"

871 defdump(st):872 mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime =st873 print "- size:", size, "bytes"

874 print "- owner:", uid, gid875 print "- created:", time.ctime(ctime)876 print "- last accessed:", time.ctime(atime)877 print "- last modified:", time.ctime(mtime)878 print "- mode:", oct(mode)879 print "- inode/dev:", ino, dev880 #881 #get stats for a filename

882 st =

883 os.stat(file)884 print "stat",885 file dump(st)886 print ## get stats for an open file fp =

887 open(file)888 st =

889 os.fstat(fp.fileno())890 print "fstat",891 file892 dump(st) <

893 /FONT >

894

897 宋体898 >

899 stat samples/sample.jpg900 - size: 4762bytes901 -owner: 0 0902 - created: Tue Sep 07 22:45:58 1999

903 - last accessed: Sun Sep 19 00:00:00 1999

904 - last modified: Sun May 19 01:42:16 1996

905 - mode: 0100666

906 - inode/dev: 0 2

907 fstat samples/sample.jpg908 - size: 4762bytes909 -owner: 0 0910 - created: Tue Sep 07 22:45:58 1999

911 - last accessed: Sun Sep 19 00:00:00 1999

912 - last modified: Sun May 19 01:42:16 1996

913 - mode: 0100666

914 - inode/dev: 0 0915 返回对象中有些属性在非 Unix 平台下是无意义的, 比如 (st_inode , st_dev )916 为 Unix 下的为每个文件提供了唯一标识, 但在其他平台可能为任意无意义数917 据 .918 stat 模块包含了很多可以处理该返回对象的常量及函数. 下面的代码展示了其919 中的一些.920 可以使用 chmod 和 utime 函数修改文件的权限模式和时间属性,如 Example921 1-33所示.922 1.4.3.2. Example 1-33. 使用 os 模块修改文件的权限和时间戳923 File: os-example-2.py924 importos925 importstat, time926 infile = "samples/sample.jpg"

927 outfile = "out.jpg"

928 #copy contents

929 fi = open(infile, "rb")930 fo = open(outfile, "wb")931 while 1:932 s = fi.read(10000)933 if nots:934 breakfo.write(s)935 fi.close() fo.close()936 #copy mode

937 andtimestamp938 st =

939 os.stat(infile) os.chmod(outfile, stat.S_IMODE(st[stat.ST_MODE]))940 os.utime(outfile, (st[stat.ST_ATIME], st[stat.ST_MTIME]))941 print "original",942 "=

943 >"print"mode",

944 oct(stat.S_IMODE(st[stat.ST_MODE]))945 print

946 "atime",947 time.ctime(st[stat.ST_ATIME])948 print "mtime", time.ctime(st[stat.ST_MTIME]) print "copy",949 "=

950 >"st=

951 os.stat(outfile)952 print "mode",953 oct(stat.S_IMODE(st[stat.ST_MODE]))954 print

955 "atime", time.ctime(st[stat.ST_ATIME]) print

956 "mtime", time.ctime(st[stat.ST_MTIME]) <

957 /FONT >

958

960 宋体961 >

962 original =>

963 mode 0666

964 atime Thu Oct 14 15:15:50 1999

965 mtime Mon Nov 13 15:42:36 1995

966 copy =

967 >

968 mode 0666

969 atime Thu Oct 14 15:15:50 1999

970 mtime Mon Nov 13 15:42:36 1995

971 1.4.4. 处理进程972 system 函数在当前进程下执行一个新命令, 并等待它完成, 如 Example 1-34

973 所示.974 1.4.4.1. Example 1-34. 使用 os 执行操作系统命令975 File: os-example-8.py976 importos977 if os.name == "nt":978 command =

979 "dir" else:980 command = "ls

981 -l"982 os.system(command) < /FONT983 ><

984 FONT985 face =

986 宋体987 >

988 -rwxrw-r-- 1 effbot effbot 76 Oct 9 14:17README989 -rwxrw-r-- 1 effbot effbot 1727 Oct 7 19:00

990 SimpleAsyncHTTP.py991 -rwxrw-r-- 1 effbot effbot 314 Oct 7 20:29 aifc-example-1.py992 -rwxrw-r-- 1 effbot effbot 259 Oct 7 20:38

993 anydbm-example-1.py994 ...995 命令通过操作系统的标准 shell 执行, 并返回 shell 的退出状态. 需要注意996 的是在 Windows 95/98下, shell 通常是 command.com , 它的推出状态总是997 0.998 由于 11os.system11 直接将命令传递给 shell , 所以如果你不检查传入参数999 的时候会很危险 (比如命令 os.system("viewer %s" %file) , 将 file 变量1000 设置为 "sample.jpg; rm -rf $HOME".... ). 如果不确定参数的安全性, 那么1001 最好使用 exec或 spawn 代替(稍后介绍).1002 exec 函数会使用新进程替换当前进程(或者说是"转到进程"). 在 Example1003 1-35 中, 字符串 "goodbye"永远不会被打印.1004 1.4.4.2. Example 1-35. 使用 os 模块启动新进程1005 File: os-exec-example-1.py1006 importos1007 importsys1008 program = "python"

1009 arguments = ["hello.py"]1010 print os.execvp(program, (program,) +tuple(arguments))1011 print "goodbye"

1012 hello again, andwelcome to the show1013 Python 提供了很多表现不同的 exec 函数. Example 1-35使用的是 execvp 函1014 数, 它会从标准路径搜索执行程序, 把第二个参数(元组)作为单独的参数传递1015 给程序, 并使用当前的环境变量来运行程序. 其他七个同类型函数请参阅1016 Python Library Reference .1017 在 Unix 环境下, 你可以通过组合使用 exec, fork 以及 wait 函数来从当前1018 程序调用另一个程序, 如 Example 1-36所示. fork 函数复制当前进程, wait1019 函数会等待一个子进程执行结束.1020 1.4.4.3. Example 1-36. 使用 os 模块调用其他程序 (Unix)1021 File: os-exec-example-2.py1022 importos1023 importsys1024 def run(program, *args):1025 pid =os.fork()1026 if notpid:1027 os.execvp(program, (program,) +args)1028 returnos.wait()[0]1029 run("python", "hello.py")1030 print "goodbye"

1031 hello again, andwelcome to the show1032 goodbye1033 fork 函数在子进程返回中返回 0 (这个进程首先从 fork 返回值), 在父进程1034 中返回一个非 0 的进程标识符(子进程的 PID ). 也就是说, 只有当我们处于1035 子进程的时候 "not pid"才为真.1036 fork 和 wait 函数在 Windows 上是不可用的, 但是你可以使用 spawn 函数,1037 如 Example 1-37所示. 不过, spawn 不会沿着路径搜索可执行文件, 你必须自1038 己处理好这些.1039 1.4.4.4. Example 1-37. 使用 os 模块调用其他程序 (Windows)1040 File: os-spawn-example-1.py1041 importos1042 importstring1043 def run(program, *args):1044 #find executable

1045 for path in string.split(os.environ["PATH"], os.pathsep):1046 file = os.path.join(path, program) + ".exe"

1047 try:1048 return os.spawnv(os.P_WAIT, file, (file,) +args)1049 exceptos.error:1050 pass

1051 raise os.error, "cannot find executable"

1052 run("python", "hello.py")1053 print "goodbye"

1054 hello again, andwelcome to the show1055 goodbye1056 spawn 函数还可用于在后台运行一个程序. Example 1-38给 run 函数添加了一1057 个可选的 mode 参数; 当设置为 os.P_NOWAIT 时, 这个脚本不会等待子程序结1058 束, 默认值 os.P_WAIT 时 spawn 会等待子进程结束.1059 其它的标志常量还有 os.P_OVERLAY ,它使得 spawn 的行为和 exec类似, 以1060 及 os.P_DETACH , 它在后台运行子进程, 与当前控制台和键盘焦点隔离.1061 1.4.4.5. Example 1-38. 使用 os 模块在后台执行程序 (Windows)1062 File: os-spawn-example-2.py1063 importos1064 importstring1065 def run(program, *args, **kw):1066 #find executable

1067 mode = kw.get("mode", os.P_WAIT)1068 for path in string.split(os.environ["PATH"], os.pathsep):1069 file = os.path.join(path, program) + ".exe"

1070 try:1071 return os.spawnv(mode, file, (file,) +args)1072 exceptos.error:1073 pass

1074 raise os.error, "cannot find executable"

1075 run("python", "hello.py", mode=os.P_NOWAIT)1076 print "goodbye"

1077 <

1078 FONT1079 face =

1080 宋体>

1081 goodbye1082 hello again, andwelcome to the show1083 Example 1-39提供了一个在 Unix 和 Windows 平台上通用的 spawn 方法.1084 1.4.4.6. Example 1-39. 使用 spawn 或 fork/exec调用其他程序1085 File: os-spawn-example-3.py1086 importos1087 importstring1088 if os.name in ("nt", "dos"):1089 exefile = ".exe"

1090 else:1091 exefile = ""

1092 def spawn(program, *args):1093 try:1094 #possible 2.0 shortcut!

1095 return os.spawnvp(program, (program,) +args)1096 exceptAttributeError:1097 pass

1098 try:1099 spawnv =

1100 os.spawnv except

1101 AttributeError: #assume it's unix

1102 pid =

1103 os.fork() if

1104 notpid: os.execvp(program,1105 (program,)1106 + args) returnos.wait()[0]1107 else: #got spawnv but

1108 no spawnp:1109 go1110 look1111 foran1112 executable for

1113 path in string.split(os.environ["PATH"], os.pathsep):1114 file =

1115 os.path.join(path, program) +

1116 exefile try: returnspawnv(os.P_WAIT, file,1117 (file,)1118 + args) except os.error: pass raise

1119 IOError, "cannot

1120 find1121 executable"# # try

1122 it out!1123 spawn("python", "hello.py")1124 print "goodbye" < /FONT >

1125

1127 宋体1128 >

1129 hello again, andwelcome to the show1130 goodbye1131 Example 1-39 首先尝试调用 spawnvp 函数. 如果该函数不存在 (一些版本/平1132 台没有这个函数), 它将继续查找一个名为 spawnv 的函数并且开始查找程序路1133 径. 作为最后的选择, 它会调用 exec和 fork 函数完成工作.1134 1.4.5. 处理守护进程(Daemon Processes)1135 Unix 系统中, 你可以使用 fork 函数把当前进程转入后台(一个"守护者

1136 /daemon"). 一般来说, 你需要派生(fork off)一个当前进程的副本, 然后终止

1137 原进程, 如 Example 1-40所示.1138 1.4.5.1. Example 1-40. 使用 os 模块使脚本作为守护执行 (Unix)1139 File: os-example-14.py1140 importos1141 importtime1142 pid =

1143 os.fork() if

1144 pid: os._exit(0)1145 #kill original print

1146 "daemon started" time.sleep(10)1147 print

1148 "daemon terminated" <

1149 /FONT1150 >

1151 需要创建一个真正的后台程序稍微有点复杂, 首先调用 setpgrp 函数创建一个1152 "进程组首领/process group leader". 否则, 向无关进程组发送的信号(同时)1153 会引起守护进程的问题:1154 os.setpgrp()1155 为了确保守护进程创建的文件能够获得程序指定的 mode flags(权限模式标1156 记?), 最好删除 user mode mask:1157 os.umask(0)1158 然后, 你应该重定向 stdout/stderr 文件, 而不能只是简单地关闭它们(如果1159 你的程序需要 stdout 或 stderr 写入内容的时候, 可能会出现意想不到的问1160 题).1161 classNullDevice:1162 defwrite(self, s):1163 pass

1164 sys.stdin.close()1165 sys.stdout =

1166 NullDevice()1167 sys.stderr =

1168 NullDevice()1169 < /FONT1170 >

1171 换言之, 由于 Python 的 print 和 C 中的 printf/fprintf 在设备(device)1172 没有连接后不会关闭你的程序, 此时守护进程中的 sys.stdout.write() 会抛1173 出一个 IOError 异常, 而你的程序依然在后台运行的很好....1174 另外, 先前例子中的 _exit 函数会终止当前进程. 而 sys.exit 不同, 如果调1175 用者(caller) 捕获了 SystemExit 异常, 程序仍然会继续执行. 如 Example1176 1-41所示.1177 1.4.5.2. Example 1-41. 使用 os 模块终止当前进程1178 File: os-example-9.py1179 importos1180 importsys1181 try:1182 sys.exit(1)1183 exceptSystemExit, value:1184 print "caught exit(%s)" %value1185 try:1186 os._exit(2)1187 exceptSystemExit, value:1188 print "caught exit(%s)" %value1189 print "bye!"

1190 caught exit(1)1191 1.5. os.path 模块1192 os.path 模块包含了各种处理长文件名(路径名)的函数. 先导入 (import) os1193 模块, 然后就可以以 os.path 访问该模块.1194 1.5.1. 处理文件名1195 os.path 模块包含了许多与平台无关的处理长文件名的函数. 也就是说, 你不1196 需要处理前后斜杠, 冒号等. 我们可以看看 Example 1-42中的样例代码.1197 1.5.1.1. Example 1-42. 使用 os.path 模块处理文件名1198 File: os-path-example-1.py1199 importos1200 filename = "my/little/pony"

1201 print "using", os.name, "..."

1202 print "split", "=>", os.path.split(filename)1203 print "splitext", "=>", os.path.splitext(filename)1204 print "dirname", "=>", os.path.dirname(filename)1205 print "basename", "=>", os.path.basename(filename)1206 print "join",1207 "=

1208 >", os.path.join(os.path.dirname(filename),

1209 os.path.basename(filename))<

1210 /FONT>

1211 <

1212 FONT face=

1213 宋体>

1214 using nt ...1215 split => ('my/little', 'pony')1216 splitext => ('my/little/pony', '')1217 dirname = > my/little1218 basename =

1219 >pony1220 join =

1221 > my/little\pony1222 注意这里的 split 只分割出最后一项(不带斜杠).1223 os.path 模块中还有许多函数允许你简单快速地获知文件名的一些特征,如1224 Example 1-43所示。1225 1.5.1.2. Example 1-43. 使用 os.path 模块检查文件名的特征1226 File: os-path-example-2.py1227 importos1228 FILES =(1229 os.curdir,1230 "/",1231 "file",1232 "/file",1233 "samples",1234 "samples/sample.jpg",1235 "directory/file",1236 "../directory/file",1237 "/directory/file"

1238 )1239 for file inFILES:1240 print file, "=>",1241 ifos.path.exists(file):1242 print "EXISTS",1243 ifos.path.isabs(file):1244 print "ISABS",1245 ifos.path.isdir(file):1246 print "ISDIR",1247 ifos.path.isfile(file):1248 print "ISFILE",1249 ifos.path.islink(file):1250 print "ISLINK",1251 ifos.path.ismount(file):1252 print "ISMOUNT",1253 print

1254 <

1255 FONT1256 face =

1257 宋体>

1258 . =>EXISTS ISDIR1259 / =>EXISTS ISABS ISDIR ISMOUNT1260 file =>

1261 /file =>ISABS1262 samples =>EXISTS ISDIR1263 samples/sample.jpg =>EXISTS ISFILE1264 directory/file =>

1265 ../directory/file =>

1266 /directory/file =>ISABS1267 expanduser 函数以与大部分Unix shell 相同的方式处理用户名快捷符号(~, 不1268 过在 Windows 下工作不正常), 如 Example 1-44所示.1269 1.5.1.3. Example 1-44. 使用 os.path 模块将用户名插入到文件名1270 File: os-path-expanduser-example-1.py1271 importos1272 print os.path.expanduser("~/.pythonrc")1273 #/home/effbot/.pythonrc

1274 expandvars 函数将文件名中的环境变量替换为对应值, 如 Example 1-45所1275 示.1276 1.5.1.4. Example 1-45. 使用 os.path 替换文件名中的环境变量1277 File: os-path-expandvars-example-1.py1278 importos1279 os.environ["USER"] = "user"

1280 print os.path.expandvars("/home/$USER/config")1281 print os.path.expandvars("$USER/folders")1282 /home/user/config1283 user/folders1284 1.5.2. 搜索文件系统1285 walk 函数会帮你找出一个目录树下的所有文件 (如 Example 1-46所示). 它1286 的参数依次是目录名, 回调函数, 以及传递给回调函数的数据对象.1287 1.5.2.1. Example 1-46. 使用 os.path 搜索文件系统1288 File: os-path-walk-example-1.py1289 importos1290 defcallback(arg, directory, files):1291 for file infiles:1292 printos.path.join(directory, file), repr(arg)1293 os.path.walk(".", callback, "secret message")1294 ./aifc-example-1.py 'secret message'

1295 ./anydbm-example-1.py 'secret message'

1296 ./array-example-1.py 'secret message'

1297 ...1298 ./samples 'secret message'

1299 ./samples/sample.jpg 'secret message'

1300 ./samples/sample.txt 'secret message'

1301 ./samples/sample.zip 'secret message'

1302 ./samples/articles 'secret message'

1303 ./samples/articles/article-1.txt 'secret message'

1304 ./samples/articles/article-2.txt 'secret message'

1305 ...1306 walk 函数的接口多少有点晦涩 (也许只是对我个人而言, 我总是记不住参数的1307 顺序). Example 1-47中展示的 index 函数会返回一个文件名列表, 你可以直1308 接使用 for-in循环处理文件.1309 1.5.2.2. Example 1-47. 使用 os.listdir 搜索文件系统1310 File: os-path-walk-example-2.py1311 importos1312 defindex(directory):1313 #like os.listdir, but traverses directory trees

1314 stack =[directory]1315 files =[]1316 whilestack:1317 directory =stack.pop()1318 for file inos.listdir(directory):1319 fullname =os.path.join(directory, file)1320 files.append(fullname)1321 if os.path.isdir(fullname) and not

1322 os.path.islink(fullname):1323 stack.append(fullname)1324 returnfiles1325 for file in index("."):1326 printfile1327 .\aifc-example-1.py1328 .\anydbm-example-1.py1329 .\array-example-1.py1330 ...1331 如果你不想列出所有的文件 (基于性能或者是内存的考虑) , Example 1-48展1332 示了另一种方法. 这里 DirectoryWalker 类的行为与序列对象相似, 一次返回1333 一个文件. (generator?)1334 1.5.2.3. Example 1-48. 使用 DirectoryWalker 搜索文件系统1335 File: os-path-walk-example-3.py1336 importos1337 classDirectoryWalker:1338 #a forward iterator that traverses a directory tree

1339 def_ _init_ _(self, directory):1340 self.stack =[directory]1341 self.files =[]1342 self.index =01343 def_ _getitem_ _(self, index):1344 while 1:1345 try:1346 file =self.files[self.index]1347 self.index = self.index + 1

1348 exceptIndexError:1349 #pop next directory from stack

1350 self.directory =self.stack.pop()1351 self.files =os.listdir(self.directory)1352 self.index =01353 else:1354 #got a filename

1355 fullname =os.path.join(self.directory, file)1356 if os.path.isdir(fullname) and not

1357 os.path.islink(fullname):1358 self.stack.append(fullname)1359 returnfullname1360 for file in DirectoryWalker("."):1361 printfile1362 .\aifc-example-1.py1363 .\anydbm-example-1.py1364 .\array-example-1.py1365 ...1366 注意 DirectoryWalker 类并不检查传递给 _ _getitem_ _ 方法的索引值. 这意1367 味着如果你越界访问序列成员(索引数字过大)的话, 这个类将不能正常工作.1368 最后, 如果你需要处理文件大小和时间戳, Example 1-49给出了一个类, 它返1369 回文件名和它的 os.stat 属性(一个元组). 这个版本在每个文件上都能节省一1370 次或两次 stat 调用( os.path.isdir 和 os.path.islink 内部都使用了1371 stat ), 并且在一些平台上运行很快.1372 1.5.2.4. Example 1-49. 使用 DirectoryStatWalker 搜索文件系统1373 File: os-path-walk-example-4.py1374 importos, stat1375 classDirectoryStatWalker:1376 #a forward iterator that traverses a directory tree, and

1377 #returns the filename and additional file information

1378 def_ _init_ _(self, directory):1379 self.stack =[directory]1380 self.files =[]1381 self.index =01382 def_ _getitem_ _(self, index):1383 while 1:1384 try:1385 file =self.files[self.index]1386 self.index = self.index + 1

1387 exceptIndexError:1388 #pop next directory from stack

1389 self.directory =self.stack.pop()1390 self.files =os.listdir(self.directory)1391 self.index =01392 else:1393 #got a filename

1394 fullname =os.path.join(self.directory, file)1395 st =os.stat(fullname)1396 mode =st[stat.ST_MODE]1397 if stat.S_ISDIR(mode) and notstat.S_ISLNK(mode):1398 self.stack.append(fullname)1399 returnfullname, st1400 for file, st in DirectoryStatWalker("."):1401 printfile, st[stat.ST_SIZE]1402 .\aifc-example-1.py 336

1403 .\anydbm-example-1.py 244

1404 .\array-example-1.py 526

1405 1.6. stat 模块1406 Example 1-50展示了 stat 模块的基本用法, 这个模块包含了一些 os.stat1407 函数中可用的常量和测试函数.1408 1.6.0.1. Example 1-50. Using the stat Module1409 File: stat-example-1.py1410 importstat1411 importos, time1412 st = os.stat("samples/sample.txt")1413 print "mode", "=>", oct(stat.S_IMODE(st[stat.ST_MODE]))1414 print "type", "=>",1415 ifstat.S_ISDIR(st[stat.ST_MODE]):1416 print "DIRECTORY",1417 ifstat.S_ISREG(st[stat.ST_MODE]):1418 print "REGULAR",1419 ifstat.S_ISLNK(st[stat.ST_MODE]):1420 print "LINK",1421 print

1422 print "size", "=>", st[stat.ST_SIZE]1423 print "last accessed", "=>", time.ctime(st[stat.ST_ATIME])1424 print "last modified", "=>", time.ctime(st[stat.ST_MTIME])1425 print "inode changed", "=>", time.ctime(st[stat.ST_CTIME])1426 mode => 0664

1427 type =>REGULAR1428 size => 305

1429 last accessed => Sun Oct 10 22:12:30 1999

1430 last modified => Sun Oct 10 18:39:37 1999

1431 inode changed => Sun Oct 10 15:26:38 1999

1432 1.7. string 模块1433 string 模块提供了一些用于处理字符串类型的函数, 如 Example 1-51所示.1434 1.7.0.1. Example 1-51. 使用 string 模块1435 File: string-example-1.py1436 importstring1437 text = "Monty Python's Flying Circus"

1438 print "upper", "=>", string.upper(text)1439 print "lower", "=>", string.lower(text)1440 print "split", "=>", string.split(text)1441 print "join", "=>", string.join(string.split(text), "+")1442 print "replace", "=>", string.replace(text, "Python", "Java")1443 print "find", "=>", string.find(text, "Python"), string.find(text,1444 "Java")1445 print "count", "=>", string.count(text, "n")1446 upper => MONTY PYTHON'S FLYING CIRCUS

1447 lower => monty python's flying circus

1448 split => ['Monty', "Python's", 'Flying', 'Circus']1449 join => Monty+Python's+Flying+Circus

1450 replace => Monty Java's Flying Circus

1451 find => 6 -1

1452 count => 3

1453 在 Python 1.5.2以及更早版本中, string 使用 strop 中的函数来实现模块功1454 能.1455 在 Python1.6和后继版本,更多的字符串操作都可以作为字符串方法来访问,1456 如 Example 1-52所示, string 模块中的许多函数只是对相对应字符串方法的1457 封装.1458 1.7.0.2. Example 1-52. 使用字符串方法替代 string 模块函数1459 File: string-example-2.py1460 text = "Monty Python's Flying Circus"

1461 print "upper", "=>", text.upper()1462 print "lower", "=>", text.lower()1463 print "split", "=>", text.split()1464 print "join", "=>", "+".join(text.split())1465 print "replace", "=>", text.replace("Python", "Perl")1466 print "find", "=>", text.find("Python"), text.find("Perl")1467 print "count", "=>", text.count("n")1468 upper => MONTY PYTHON'S FLYING CIRCUS

1469 lower => monty python's flying circus

1470 split => ['Monty', "Python's", 'Flying', 'Circus']1471 join => Monty+Python's+Flying+Circus

1472 replace => Monty Perl's Flying Circus

1473 find => 6 -1

1474 count => 3

1475 为了增强模块对字符的处理能力, 除了字符串方法, string 模块还包含了类型1476 转换函数用于把字符串转换为其他类型, (如 Example 1-53所示).1477 1.7.0.3. Example 1-53. 使用 string 模块将字符串转为数字1478 File: string-example-3.py1479 importstring1480 print int("4711"),1481 print string.atoi("4711"),1482 print string.atoi("11147", 8), #octal 八进制

1483 print string.atoi("1267", 16), #hexadecimal 十六进制

1484 print string.atoi("3mv", 36) #whatever...

1485 print string.atoi("4711", 0),1486 print string.atoi("04711", 0),1487 print string.atoi("0x4711", 0)1488 print float("4711"),1489 print string.atof("1"),1490 print string.atof("1.23e5")1491 4711 4711 4711 4711 4711

1492 4711 2505 18193

1493 4711.0 1.0 123000.0

1494 大多数情况下 (特别是当你使用的是1.6及更高版本时) ,你可以使用 int 和1495 float 函数代替 string 模块中对应的函数。1496 atoi 函数可以接受可选的第二个参数, 指定数基(number base). 如果数基为1497 0, 那么函数将检查字符串的前几个字符来决定使用的数基: 如果为 "0x,"数1498 基将为 16 (十六进制), 如果为 "0," 则数基为 8 (八进制). 默认数基值为 10

1499 (十进制), 当你未传递参数时就使用这个值.1500 在 1.6及以后版本中, int 函数和 atoi 一样可以接受第二个参数. 与字符串1501 版本函数不一样的是 , int 和 float 可以接受 Unicode 字符串对象.1502 1.8. re 模块1503 "Some people, when confronted with a problem, think 'I know, I'll use

1504 regular expressions.'Now they have two problems."

1505 -Jamie Zawinski, on comp.lang.emacs1506 re 模块提供了一系列功能强大的正则表达式 (regular expression) 工具, 它1507 们允许你快速检查给定字符串是否与给定的模式匹配 (使用 match 函数), 或1508 者包含这个模式 (使用 search 函数). 正则表达式是以紧凑(也很神秘)的语法1509 写出的字符串模式.1510 match 尝试从字符串的起始匹配一个模式, 如 Example 1-54所示. 如果模式1511 匹配了某些内容 (包括空字符串, 如果模式允许的话) , 它将返回一个匹配对1512 象. 使用它的 group 方法可以找出匹配的内容.1513 1.8.0.1. Example 1-54. 使用 re 模块来匹配字符串1514 File: re-example-1.py1515 importre1516 text = "The Attila the Hun Show"

1517 #a single character 单个字符

1518 m = re.match(".", text)1519 if m: print repr("."), "=>", repr(m.group(0))1520 #any string of characters 任何字符串

1521 m = re.match(".*", text)1522 if m: print repr(".*"), "=>", repr(m.group(0))1523 #a string of letters (at least one) 只包含字母的字符串(至少一个)

1524 m = re.match("\w+", text)1525 if m: print repr("\w+"), "=>", repr(m.group(0))1526 #a string of digits 只包含数字的字符串

1527 m = re.match("\d+", text)1528 if m: print repr("\d+"), "=>", repr(m.group(0))1529 '.' => 'T'

1530 '.*' => 'The Attila the Hun Show'

1531 '\\w+' => 'The'

1532 可以使用圆括号在模式中标记区域. 找到匹配后, group 方法可以抽取这些区1533 域的内容,如 Example 1-55 所示. group(1) 会返回第一组的内容, group(2)1534 返回第二组的内容, 这样... 如果你传递多个组数给 group 函数, 它会返回一1535 个元组.1536 1.8.0.2. Example 1-55. 使用 re 模块抽出匹配的子字符串1537 File: re-example-2.py1538 importre1539 text ="10/15/99"

1540 m = re.match("(\d{2})/(\d{2})/(\d{2,4})", text)1541 ifm:1542 print m.group(1, 2, 3)1543 ('10', '15', '99')1544 search 函数会在字符串内查找模式匹配, 如 Example 1-56所示. 它在所有可1545 能的字符位置尝试匹配模式, 从最左边开始, 一旦找到匹配就返回一个匹配对1546 象. 如果没有找到相应的匹配, 就返回 None .1547 1.8.0.3. Example 1-56. 使用 re 模块搜索子字符串1548 File: re-example-3.py1549 importre1550 text = "Example 3: There is 1 date 10/25/95 in here!"

1551 m = re.search("(\d{1,2})/(\d{1,2})/(\d{2,4})", text)1552 print m.group(1), m.group(2), m.group(3)1553 month, day, year = m.group(1, 2, 3)1554 printmonth, day, year1555 date =m.group(0)1556 printdate1557 10 25 95

1558 10 25 95

1559 10/25/95

1560 Example 1-57中展示了 sub 函数, 它可以使用另个字符串替代匹配模式.1561 1.8.0.4. Example 1-57. 使用 re 模块替换子字符串1562 File: re-example-4.py1563 importre1564 text = "you're no fun anymore..."

1565 #literal replace (string.replace is faster)

1566 #文字替换 (string.replace 速度更快)

1567 print re.sub("fun", "entertaining", text)1568 #collapse all non-letter sequences to a single dash

1569 #将所有非字母序列转换为一个"-"(dansh,破折号)

1570 print re.sub("[^\w]+", "-", text)1571 #convert all words to beeps

1572 #将所有单词替换为 BEEP

1573 print re.sub("\S+", "-BEEP-", text)1574 you're no entertaining anymore...

1575 you-re-no-fun-anymore-

1576 -BEEP- -BEEP- -BEEP- -BEEP-

1577 你也可以通过回调 (callback) 函数使用 sub 来替换指定模式. Example 1-58

1578 展示了如何预编译模式.1579 1.8.0.5. Example 1-58. 使用 re 模块替换字符串(通过回调函数)1580 File: re-example-5.py1581 importre1582 importstring1583 text = "a line of text\\012another line of text\\012etc..."

1584 defoctal(match):1585 #replace octal code with corresponding ASCII character

1586 #使用对应 ASCII 字符替换八进制代码

1587 return chr(string.atoi(match.group(1), 8))1588 octal_pattern = re.compile(r"\\(\d\d\d)")1589 printtext1590 printoctal_pattern.sub(octal, text)1591 a line of text\012another line of text\012etc...1592 a line of text1593 another line of text1594 etc...1595 如果你不编译, re 模块会为你缓存一个编译后版本, 所有的小脚本中, 通常不1596 需要编译正则表达式. Python1.5.2 中, 缓存中可以容纳 20个匹配模式, 而1597 在 2.0 中, 缓存则可以容纳 100个匹配模式.1598 最后, Example 1-59用一个模式列表匹配一个字符串. 这些模式将会组合为一1599 个模式, 并预编译以节省时间.1600 1.8.0.6. Example 1-59. 使用 re 模块匹配多个模式中的一个1601 File: re-example-6.py1602 importre, string1603 defcombined_pattern(patterns):1604 p =re.compile(1605 string.join(map(lambda x: "("+x+")", patterns), "|")1606 )1607 def fixup(v, m=p.match, r=range(0,len(patterns))):1608 try:1609 regs =m(v).regs1610 exceptAttributeError:1611 return None #no match, so m.regs will fail

1612 else:1613 for i inr:1614 if regs[i+1] != (-1, -1):1615 returni1616 returnfixup1617 #1618 #try it out!

1619 patterns =[1620 r"\d+",1621 r"abc\d{2,4}",1622 r"p\w+"

1623 ]1624 p =combined_pattern(patterns)1625 print p("129391")1626 print p("abc800")1627 print p("abc1600")1628 print p("python")1629 print p("perl")1630 print p("tcl")1631 01632 1

1633 1

1634 2

1635 2

1636 None1637 1.9. math 模块1638 math 模块实现了许多对浮点数的数学运算函数. 这些函数一般是对平台 C 库1639 中同名函数的简单封装, 所以一般情况下, 不同平台下计算的结果可能稍微地1640 有所不同, 有时候甚至有很大出入. Example 1-60展示了如何使用 math 模块.1641 1.9.0.1. Example 1-60. 使用 math 模块1642 File: math-example-1.py1643 importmath1644 print "e", "=>", math.e1645 print "pi", "=>", math.pi1646 print "hypot", "=>", math.hypot(3.0, 4.0)1647 #and many others...

1648 e => 2.71828182846

1649 pi => 3.14159265359

1650 hypot => 5.0

1651 完整函数列表请参阅 Python Library Reference .1652 1.10. cmath 模块1653 Example 1-61所展示的 cmath 模块包含了一些用于复数运算的函数.1654 1.10.0.1. Example 1-61. 使用 cmath 模块1655 File: cmath-example-1.py1656 importcmath1657 print "pi", "=>", cmath.pi1658 print "sqrt(-1)", "=>", cmath.sqrt(-1)1659 pi => 3.14159265359

1660 sqrt(-1) => 1j

1661 完整函数列表请参阅 Python Library Reference .1662 1.11. operator 模块1663 operator 模块为 Python 提供了一个 "功能性"的标准操作符接口. 当使用1664 map 以及 filter 一类的函数的时候, operator 模块中的函数可以替换一些1665 lambda函式. 而且这些函数在一些喜欢写晦涩代码的程序员中很流行.1666 Example 1-62展示了 operator 模块的一般用法.1667 1.11.0.1. Example 1-62. 使用 operator 模块1668 File: operator-example-1.py1669 importoperator1670 sequence = 1, 2, 4

1671 print "add", "=>", reduce(operator.add, sequence)1672 print "sub", "=>", reduce(operator.sub, sequence)1673 print "mul", "=>", reduce(operator.mul, sequence)1674 print "concat", "=>", operator.concat("spam", "egg")1675 print "repeat", "=>", operator.repeat("spam", 5)1676 print "getitem", "=>", operator.getitem(sequence, 2)1677 print "indexOf", "=>", operator.indexOf(sequence, 2)1678 print "sequenceIncludes", "=>", operator.sequenceIncludes(sequence, 3)1679 add => 7

1680 sub => -5

1681 mul => 8

1682 concat =>spamegg1683 repeat =>spamspamspamspamspam1684 getitem => 4

1685 indexOf => 1

1686 sequenceIncludes =>01687 Example 1-63展示了一些可以用于检查对象类型的 operator 函数.1688 1.11.0.2. Example 1-63. 使用 operator 模块检查类型1689 File: operator-example-2.py1690 importoperator1691 importUserList1692 defdump(data):1693 print type(data), "=>",1694 ifoperator.isCallable(data):1695 print "CALLABLE",1696 ifoperator.isMappingType(data):1697 print "MAPPING",1698 ifoperator.isNumberType(data):1699 print "NUMBER",1700 ifoperator.isSequenceType(data):1701 print "SEQUENCE",1702 print

1703 dump(0)1704 dump("string")1705 dump("string"[0])1706 dump([1, 2, 3])1707 dump((1, 2, 3))1708 dump({"a": 1})1709 dump(len) #function 函数

1710 dump(UserList) #module 模块

1711 dump(UserList.UserList) #class 类

1712 dump(UserList.UserList()) #instance 实例

1713 =>NUMBER1714 =>SEQUENCE1715 =>SEQUENCE1716 =>SEQUENCE1717 =>SEQUENCE1718 =>MAPPING1719 =>CALLABLE1720 =>

1721 =>CALLABLE1722 =>MAPPING NUMBER SEQUENCE1723 这里需要注意 operator 模块使用非常规的方法处理对象实例. 所以使用1724 isNumberType , isMappingType , 以及 isSequenceType 函数的时候要小心,1725 这很容易降低代码的扩展性.1726 同样需要注意的是一个字符串序列成员 (单个字符) 也是序列. 所以当在递归1727 函数使用 isSequenceType 来截断对象树的时候, 别把普通字符串作为参数(或1728 者是任何包含字符串的序列对象).1729 1.12. copy 模块1730 copy 模块包含两个函数, 用来拷贝对象, 如 Example 1-64所示.1731 copy(object) => object 创建给定对象的 "浅/浅层(shallow)"拷贝(copy).1732 这里 "浅/浅层(shallow)"的意思是复制对象本身, 但当对象是一个容器1733 (container) 时, 它的成员仍然指向原来的成员对象.1734 1.12.0.1. Example 1-64. 使用 copy 模块复制对象1735 File: copy-example-1.py1736 importcopy1737 a = [[1],[2],[3]]1738 b =copy.copy(a)1739 print "before", "=>"

1740 printa1741 printb1742 #modify original

1743 a[0][0] =01744 a[1] =None1745 print "after", "=>"

1746 printa1747 printb1748 before =>

1749 [[1], [2], [3]]1750 [[1], [2], [3]]1751 after =>

1752 [[0], None, [3]]1753 [[0], [2], [3]]1754 你也可以使用[:]语句 (完整切片) 来对列表进行浅层复制, 也可以使用 copy1755 方法复制字典.1756 相反地, deepcopy(object) =>object 创建一个对象的深层拷贝(deepcopy),1757 如 Example 1-65所示, 当对象为一个容器时, 所有的成员都被递归地复制了。1758 1.12.0.2. Example 1-65. 使用 copy 模块复制集合(Collections)1759 File: copy-example-2.py1760 importcopy1761 a = [[1],[2],[3]]1762 b =copy.deepcopy(a)1763 print "before", "=>"

1764 printa1765 printb1766 #modify original

1767 a[0][0] =01768 a[1] =None1769 print "after", "=>"

1770 printa1771 printb1772 before =>

1773 [[1], [2], [3]]1774 [[1], [2], [3]]1775 after =>

1776 [[0], None, [3]]1777 [[1], [2], [3]]1778 1.13. sys 模块1779 sys 模块提供了许多函数和变量来处理 Python 运行时环境的不同部分.1780 1.13.1. 处理命令行参数1781 在解释器启动后, argv 列表包含了传递给脚本的所有参数, 如 Example 1-66

1782 所示. 列表的第一个元素为脚本自身的名称.1783 1.13.1.1. Example 1-66. 使用sys 模块获得脚本的参数1784 File: sys-argv-example-1.py1785 importsys1786 print "script name is", sys.argv[0]1787 if len(sys.argv) > 1:1788 print "there are", len(sys.argv)-1, "arguments:"

1789 for arg in sys.argv[1:]:1790 printarg1791 else:1792 print "there are no arguments!"

1793 script name is sys-argv-example-1.py1794 there are no arguments!1795 如果是从标准输入读入脚本 (比如 "python < sys-argv-example-1.py"), 脚1796 本的名称将被设置为空串. 如果把脚本作为字符串传递给python (使用 -c 选1797 项), 脚本名会被设置为 "-c".1798 1.13.2. 处理模块1799 path 列表是一个由目录名构成的列表, Python 从中查找扩展模块( Python 源1800 模块, 编译模块,或者二进制扩展). 启动 Python 时,这个列表从根据内建规则,1801 PYTHONPATH 环境变量的内容, 以及注册表( Windows 系统)等进行初始化. 由1802 于它只是一个普通的列表, 你可以在程序中对它进行操作, 如 Example 1-67

1803 所示.1804 1.13.2.1. Example 1-67. 使用sys 模块操作模块搜索路径1805 File: sys-path-example-1.py1806 importsys1807 print "path has", len(sys.path), "members"

1808 #add the sample directory to the path

1809 sys.path.insert(0, "samples")1810 importsample1811 #nuke the path

1812 sys.path =[]1813 import random #oops!

1814 path has 7members1815 this isthe sample module!1816 Traceback (innermost last):1817 File "sys-path-example-1.py", line 11, in?1818 import random #oops!

1819 ImportError: No module named random1820 builtin_module_names 列表包含 Python 解释器中所有内建模块的名称,1821 Example 1-68给出了它的样例代码.1822 1.13.2.2. Example 1-68. 使用sys 模块查找内建模块1823 File: sys-builtin-module-names-example-1.py1824 importsys1825 defdump(module):1826 print module, "=>",1827 if module insys.builtin_module_names:1828 print ""

1829 else:1830 module =_ _import_ _(module)1831 printmodule._ _file_ _1832 dump("os")1833 dump("sys")1834 dump("string")1835 dump("strop")1836 dump("zlib")1837 os =>C:\python\lib\os.pyc1838 sys =>

1839 string =>C:\python\lib\string.pyc1840 strop =>

1841 zlib =>C:\python\zlib.pyd1842 modules 字典包含所有加载的模块. import语句在从磁盘导入内容之前会先检1843 查这个字典.1844 正如你在 Example 1-69中所见到的, Python 在处理你的脚本之前就已经导入1845 了很多模块.1846 1.13.2.3. Example 1-69. 使用sys 模块查找已导入的模块1847 File: sys-modules-example-1.py1848 importsys1849 printsys.modules.keys()1850 ['os.path', 'os', 'exceptions', '_ _main_ _', 'ntpath', 'strop', 'nt',1851 'sys', '_ _builtin_ _', 'site', 'signal', 'UserDict', 'string', 'stat']1852 1.13.3. 处理引用记数1853 getrefcount 函数 (如 Example 1-70 所示) 返回给定对象的引用记数 -也就1854 是这个对象使用次数. Python 会跟踪这个值, 当它减少为0 的时候, 就销毁这1855 个对象.1856 1.13.3.1. Example 1-70. 使用sys 模块获得引用记数1857 File: sys-getrefcount-example-1.py1858 importsys1859 variable = 1234

1860 printsys.getrefcount(0)1861 printsys.getrefcount(variable)1862 printsys.getrefcount(None)1863 50

1864 3

1865 192

1866 注意这个值总是比实际的数量大, 因为该函数本身在确定这个值的时候依赖这1867 个对象.1868 == 检查主机平台===

1869 Example 1-71展示了 platform 变量, 它包含主机平台的名称.1870 1.13.3.2. Example 1-71. 使用sys 模块获得当前平台1871 File: sys-platform-example-1.py1872 importsys1873 #1874 #emulate "import os.path" (sort of)...

1875 if sys.platform == "win32":1876 importntpath1877 pathmodule =ntpath1878 elif sys.platform == "mac":1879 importmacpath1880 pathmodule =macpath1881 else:1882 #assume it's a posix platform

1883 importposixpath1884 pathmodule =posixpath1885 printpathmodule1886 典型的平台有Windows 9X/NT(显示为 win32 ), 以及 Macintosh(显示为 mac ) .1887 对于 Unix 系统而言, platform 通常来自 "uname -r"命令的输出, 例如1888 irix6 , linux2 , 或者 sunos5 (Solaris).1889 1.13.4. 跟踪程序1890 setprofiler 函数允许你配置一个分析函数(profiling function). 这个函数1891 会在每次调用某个函数或方法时被调用(明确或隐含的), 或是遇到异常的时候1892 被调用. 让我们看看 Example 1-72的代码.1893 1.13.4.1. Example 1-72. 使用sys 模块配置分析函数1894 File: sys-setprofiler-example-1.py1895 importsys1896 deftest(n):1897 j =01898 for i inrange(n):1899 j = j +i1900 returnn1901 defprofiler(frame, event, arg):1902 print event, frame.f_code.co_name, frame.f_lineno, "->", arg1903 #profiler is activated on the next call, return, or exception

1904 #分析函数将在下次函数调用, 返回, 或异常时激活

1905 sys.setprofile(profiler)1906 #profile this function call

1907 #分析这次函数调用

1908 test(1)1909 #disable profiler

1910 #禁用分析函数

1911 sys.setprofile(None)1912 #don't profile this call

1913 #不会分析这次函数调用

1914 test(2)1915 call test 3 ->None1916 return test 7 -> 1

1917 基于该函数, profile 模块提供了一个完整的分析器框架.1918 Example 1-73中的 settrace 函数与此类似, 但是 trace 函数会在解释器每1919 执行到新的一行时被调用.1920 1.13.4.2. Example 1-73. 使用sys 模块配置单步跟踪函数1921 File: sys-settrace-example-1.py1922 importsys1923 deftest(n):1924 j =01925 for i inrange(n):1926 j = j +i1927 returnn1928 deftracer(frame, event, arg):1929 print event, frame.f_code.co_name, frame.f_lineno, "->", arg1930 returntracer1931 #tracer is activated on the next call, return, or exception

1932 #跟踪器将在下次函数调用, 返回, 或异常时激活

1933 sys.settrace(tracer)1934 #trace this function call

1935 #跟踪这次函数调用

1936 test(1)1937 #disable tracing

1938 #禁用跟踪器

1939 sys.settrace(None)1940 #don't trace this call

1941 #不会跟踪这次函数调用

1942 test(2)1943 call test 3 ->None1944 line test 3 ->None1945 line test 4 ->None1946 line test 5 ->None1947 line test 5 ->None1948 line test 6 ->None1949 line test 5 ->None1950 line test 7 ->None1951 return test 7 -> 1

1952 基于该函数提供的跟踪功能, pdb 模块提供了完整的调试( debug )框架.1953 1.13.5. 处理标准输出/输入1954 stdin , stdout , 以及 stderr 变量包含与标准 I/O 流对应的流对象. 如果需1955 要更好地控制输出,而 print不能满足你的要求, 它们就是你所需要的. 你也1956 可以 替换 它们, 这时候你就可以重定向输出和输入到其它设备( device ), 或1957 者以非标准的方式处理它们. 如 Example 1-74所示.1958 1.13.5.1. Example 1-74. 使用sys 重定向输出1959 File: sys-stdout-example-1.py1960 importsys1961 importstring1962 classRedirect:1963 def_ _init_ _(self, stdout):1964 self.stdout =stdout1965 defwrite(self, s):1966 self.stdout.write(string.lower(s))1967 #redirect standard output (including the print statement)

1968 #重定向标准输出(包括print 语句)

1969 old_stdout =sys.stdout1970 sys.stdout =Redirect(sys.stdout)1971 print "HEJA SVERIGE",1972 print "FRISKT HUM\303\226R"

1973 #restore standard output

1974 #恢复标准输出

1975 sys.stdout =old_stdout1976 print "M\303\205\303\205\303\205\303\205L!"

1977 heja sverige friskt hum\303\266r1978 M\303\205\303\205\303\205\303\205L!1979 要重定向输出只要创建一个对象, 并实现它的 write 方法.1980 (除非 C 类型的实例外:Python 使用一个叫做 softspace 的整数属性来控制输1981 出中的空白. 如果没有这个属性, Python 将把这个属性附加到这个对象上. 你1982 不需要在使用 Python 对象时担心, 但是在重定向到一个 C 类型时, 你应该确1983 保该类型支持 softspace 属性.)1984 1.13.6. 退出程序1985 执行至主程序的末尾时,解释器会自动退出. 但是如果需要中途退出程序, 你可1986 以调用 sys.exit 函数, 它带有一个可选的整数参数返回给调用它的程序.1987 Example 1-75给出了范例.1988 1.13.6.1. Example 1-75. 使用sys 模块退出程序1989 File: sys-exit-example-1.py1990 importsys1991 print "hello"

1992 sys.exit(1)1993 print "there"

1994 hello1995 注意 sys.exit 并不是立即退出. 而是引发一个 SystemExit 异常. 这意味着1996 你可以在主程序中捕获对 sys.exit 的调用, 如 Example 1-76所示.1997 1.13.6.2. Example 1-76. 捕获sys.exit 调用1998 File: sys-exit-example-2.py1999 importsys2000 print "hello"

2001 try:2002 sys.exit(1)2003 exceptSystemExit:2004 pass

2005 print "there"

2006 hello2007 there2008 如果准备在退出前自己清理一些东西(比如删除临时文件), 你可以配置一个 "2009 退出处理函数"(exit handler), 它将在程序退出的时候自动被调用. 如

2010 Example 1-77所示.2011 1.13.6.3. Example 1-77. 另一种捕获sys.exit 调用的方法2012 File: sys-exitfunc-example-1.py2013 importsys2014 defexitfunc():2015 print "world"

2016 sys.exitfunc =exitfunc2017 print "hello"

2018 sys.exit(1)2019 print "there" #never printed # 不会被 print

2020 hello2021 world2022 在 Python 2.0以后, 你可以使用 atexit 模块来注册多个退出处理函数.2023 1.14. atexit 模块2024 (用于2.0 版本及以上) atexit 模块允许你注册一个或多个终止函数(暂且这么2025 叫), 这些函数将在解释器终止前被自动调用.2026 调用 register 函数, 便可以将函数注册为终止函数, 如 Example 1-78所示.2027 你也可以添加更多的参数, 这些将作为 exit 函数的参数传递.2028 1.14.0.1. Example 1-78. 使用 atexit 模块2029 File: atexit-example-1.py2030 importatexit2031 def exit(*args):2032 print "exit", args2033 #register two exit handler

2034 atexit.register(exit)2035 atexit.register(exit, 1)2036 atexit.register(exit, "hello", "world")2037 exit ('hello', 'world')2038 exit (1,)2039 exit ()2040 该模块其实是一个对 sys.exitfunc 钩子( hook )的简单封装.2041 1.15. time 模块2042 time 模块提供了一些处理日期和一天内时间的函数. 它是建立在 C 运行时库2043 的简单封装.2044 给定的日期和时间可以被表示为浮点型(从参考时间, 通常是 1970.1.1到现在2045 经过的秒数. 即 Unix 格式), 或者一个表示时间的 struct (类元组).2046 1.15.1. 获得当前时间2047 Example 1-79展示了如何使用 time 模块获取当前时间.2048 1.15.1.1. Example 1-79. 使用 time 模块获取当前时间2049 File: time-example-1.py2050 importtime2051 now =time.time()2052 print now, "seconds since", time.gmtime(0)[:6]2053 print

2054 print "or in other words:"

2055 print "- local time:", time.localtime(now)2056 print "- utc:", time.gmtime(now)2057 937758359.77 seconds since (1970, 1, 1, 0, 0, 0)2058 or inother words:2059 - local time: (1999, 9, 19, 18, 25, 59, 6, 262, 1)2060 - utc: (1999, 9, 19, 16, 25, 59, 6, 262, 0)2061 localtime 和 gmtime 返回的类元组包括年, 月, 日, 时, 分, 秒, 星期, 一2062 年的第几天, 日光标志. 其中年是一个四位数(在有千年虫问题的平台上另有规2063 定, 但还是四位数), 星期从星期一(数字 0 代表)开始, 1月1 日是一年的第一2064 天.2065 1.15.2. 将时间值转换为字符串2066 你可以使用标准的格式化字符串把时间对象转换为字符串, 不过 time 模块已2067 经提供了许多标准转换函数, 如 Example 1-80所示.2068 1.15.2.1. Example 1-80. 使用 time 模块格式化时间输出2069 File: time-example-2.py2070 importtime2071 now =time.localtime(time.time())2072 printtime.asctime(now)2073 print time.strftime("%y/%m/%d %H:%M", now)2074 print time.strftime("%a %b %d", now)2075 print time.strftime("%c", now)2076 print time.strftime("%I %p", now)2077 print time.strftime("%Y-%m-%d %H:%M:%S %Z", now)2078 #do it by hand...

2079 year, month, day, hour, minute, second, weekday, yearday, daylight =now2080 print "%04d-%02d-%02d" %(year, month, day)2081 print "%02d:%02d:%02d" %(hour, minute, second)2082 print ("MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN")[weekday], yearday2083 Sun Oct 10 21:39:24 1999

2084 99/10/10 21:39

2085 Sun Oct 10

2086 Sun Oct 10 21:39:24 1999

2087 09PM2088 1999-10-10 21:39:24CEST2089 1999-10-10

2090 21:39:24

2091 SUN 283

2092 1.15.3. 将字符串转换为时间对象2093 在一些平台上, time 模块包含了 strptime 函数, 它的作用与 strftime 相反.2094 给定一个字符串和模式, 它返回相应的时间对象, 如 Example 1-81所示.2095 1.15.3.1. Example 1-81. 使用 time.strptime 函数解析时间2096 File: time-example-6.py2097 importtime2098 #make sure we have a strptime function!

2099 #确认有函数 strptime

2100 try:2101 strptime =time.strptime2102 exceptAttributeError:2103 from strptime importstrptime2104 print strptime("31 Nov 00", "%d %b %y")2105 print strptime("1 Jan 70 1:30pm", "%d %b %y %I:%M%p")2106 只有在系统的 C 库提供了相应的函数的时候, time.strptime 函数才可以使用.2107 对于没有提供标准实现的平台, Example 1-82提供了一个不完全的实现.2108 1.15.3.2. Example 1-82. strptime 实现2109 File: strptime.py2110 importre2111 importstring2112 MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",2113 "Sep", "Oct", "Nov", "Dec"]2114 SPEC ={2115 #map formatting code to a regular expression fragment

2116 "%a": "(?P[a-z]+)",2117 "%A": "(?P[a-z]+)",2118 "%b": "(?P[a-z]+)",2119 "%B": "(?P[a-z]+)",2120 "%C": "(?P\d\d?)",2121 "%d": "(?P\d\d?)",2122 "%D": "(?P\d\d?)/(?P\d\d?)/(?P\d\d)",2123 "%e": "(?P\d\d?)",2124 "%h": "(?P[a-z]+)",2125 "%H": "(?P\d\d?)",2126 "%I": "(?P\d\d?)",2127 "%j": "(?P\d\d?\d?)",2128 "%m": "(?P\d\d?)",2129 "%M": "(?P\d\d?)",2130 "%p": "(?Pam|pm)",2131 "%R": "(?P\d\d?):(?P\d\d?)",2132 "%S": "(?P\d\d?)",2133 "%T": "(?P\d\d?):(?P\d\d?):(?P\d\d?)",2134 "%U": "(?P\d\d)",2135 "%w": "(?P\d)",2136 "%W": "(?P\d\d)",2137 "%y": "(?P\d\d)",2138 "%Y": "(?P\d\d\d\d)",2139 "%%": "%"

2140 }2141 classTimeParser:2142 def_ _init_ _(self, format):2143 #convert strptime format string to regular expression

2144 format = string.join(re.split("(?:\s|%t|%n)+", format))2145 pattern =[]2146 try:2147 for spec in re.findall("%\w|%%|.", format):2148 if spec[0] == "%":2149 spec =SPEC[spec]2150 pattern.append(spec)2151 exceptKeyError:2152 raise ValueError, "unknown specificer: %s" %spec2153 self.pattern = re.compile("(?i)" + string.join(pattern, ""))2154 defmatch(self, daytime):2155 #match time string

2156 match =self.pattern.match(daytime)2157 if notmatch:2158 raise ValueError, "format mismatch"

2159 get =match.groupdict().get2160 tm = [0] * 9

2161 #extract date elements

2162 y = get("year")2163 ify:2164 y =int(y)2165 if y < 68:2166 y = 2000 +y2167 elif y < 100:2168 y = 1900 +y2169 tm[0] =y2170 m = get("month")2171 ifm:2172 if m inMONTHS:2173 m = MONTHS.index(m) + 1

2174 tm[1] =int(m)2175 d = get("day")2176 if d: tm[2] =int(d)2177 #extract time elements

2178 h = get("hour")2179 ifh:2180 tm[3] =int(h)2181 else:2182 h = get("hour12")2183 ifh:2184 h =int(h)2185 if string.lower(get("ampm12", "")) == "pm":2186 h = h + 12

2187 tm[3] =h2188 m = get("minute")2189 if m: tm[4] =int(m)2190 s = get("second")2191 if s: tm[5] =int(s)2192 #ignore weekday/yearday for now

2193 returntuple(tm)2194 def strptime(string, format="%a %b %d %H:%M:%S %Y"):2195 returnTimeParser(format).match(string)2196 if _ _name_ _ == "_ _main_ _":2197 #try it out

2198 importtime2199 print strptime("2000-12-20 01:02:03", "%Y-%m-%d %H:%M:%S")2200 printstrptime(time.ctime(time.time()))2201 (2000, 12, 20, 1, 2, 3, 0, 0, 0)2202 (2000, 11, 15, 12, 30, 45, 0, 0, 0)2203 1.15.4. 转换时间值2204 将时间元组转换回时间值非常简单, 至少我们谈论的当地时间 (local time)2205 如此. 只要把时间元组传递给 mktime 函数, 如 Example 1-83所示.2206 1.15.4.1. Example 1-83. 使用 time 模块将本地时间元组转换为时间值(整2207 数)2208 File: time-example-3.py2209 importtime2210 t0 =time.time()2211 tm =time.localtime(t0)2212 printtm2213 printt02214 printtime.mktime(tm)2215 (1999, 9, 9, 0, 11, 8, 3, 252, 1)2216 936828668.16

2217 936828668.0

2218 但是, 1.5.2版本的标准库没有提供能将 UTC 时间 (Universal Time,2219 Coordinated: 特林威治标准时间)转换为时间值的函数 ( Python 和对应底层2220 C 库都没有提供). Example 1-84提供了该函数的一个 Python 实现, 称为2221 timegm .2222 1.15.4.2. Example 1-84. 将 UTC 时间元组转换为时间值(整数)2223 File: time-example-4.py2224 importtime2225 def _d(y, m, d, days=(0,31,59,90,120,151,181,212,243,273,304,334,365)):2226 #map a date to the number of days from a reference point

2227 return (((y - 1901)*1461)/4 + days[m-1] + d +

2228 ((m > 2 and not y % 4 and (y % 100 or not y % 400)) and 1))2229 def timegm(tm, epoch=_d(1970,1,1)):2230 year, month, day, h, m, s = tm[:6]2231 assert year >= 1970

2232 assert 1 <= month <= 12

2233 return (_d(year, month, day) - epoch)*86400 + h*3600 + m*60 +s2234 t0 =time.time()2235 tm =time.gmtime(t0)2236 printtm2237 printt02238 printtimegm(tm)2239 (1999, 9, 8, 22, 12, 12, 2, 251, 0)2240 936828732.48

2241 936828732

2242 从 1.6版本开始, calendar 模块提供了一个类似的函数 calendar.timegm .2243 1.15.5. Timing 相关2244 time 模块可以计算 Python 程序的执行时间, 如 Example 1-85所示. 你可以2245 测量 "wall time" (real world time), 或是"进程时间"(消耗的 CPU 时间).2246 1.15.5.1. Example 1-85. 使用 time 模块评价算法2247 File: time-example-5.py2248 importtime2249 defprocedure():2250 time.sleep(2.5)2251 #measure process time

2252 t0 =time.clock()2253 procedure()2254 print time.clock() - t0, "seconds process time"

2255 #measure wall time

2256 t0 =time.time()2257 procedure()2258 print time.time() - t0, "seconds wall time"

2259 0.0seconds process time2260 2.50903499126seconds wall time2261 并不是所有的系统都能测量真实的进程时间. 一些系统中(包括 Windows ),2262 clock 函数通常测量从程序启动到测量时的 wall time.2263 进程时间的精度受限制. 在一些系统中, 它超过 30分钟后进程会被清理. (原2264 文: On many systems, it wraps around after just over 30minutes.)2265 另参见 timing 模块( Windows 下的朋友不用忙活了,没有地~), 它可以测量两2266 个事件之间的 wall time.2267 1.16. types 模块2268 types 模块包含了标准解释器定义的所有类型的类型对象, 如 Example 1-86

2269 所示. 同一类型的所有对象共享一个类型对象. 你可以使用 is来检查一个对2270 象是不是属于某个给定类型.2271 1.16.0.1. Example 1-86. 使用 types 模块2272 File: types-example-1.py2273 importtypes2274 defcheck(object):2275 printobject,2276 if type(object) istypes.IntType:2277 print "INTEGER",2278 if type(object) istypes.FloatType:2279 print "FLOAT",2280 if type(object) istypes.StringType:2281 print "STRING",2282 if type(object) istypes.ClassType:2283 print "CLASS",2284 if type(object) istypes.InstanceType:2285 print "INSTANCE",2286 print

2287 check(0)2288 check(0.0)2289 check("0")2290 classA:2291 pass

2292 classB:2293 pass

2294 check(A)2295 check(B)2296 a =A()2297 b =B()2298 check(a)2299 check(b)2300 0 INTEGER2301 0.0FLOAT2302 0 STRING2303 A CLASS2304 B CLASS2305 INSTANCE2306 INSTANCE2307 注意所有的类都具有相同的类型, 所有的实例也是一样. 要测试一个类或者实2308 例所属的类, 可以使用内建的 issubclass 和 isinstance 函数.2309 types 模块在第一次引入的时候会破坏当前的异常状态. 也就是说, 不要在异2310 常处理语句块中导入该模块 (或其他会导入它的模块 ) .2311 1.17. gc 模块2312 (可选, 2.0及以后版本) gc 模块提供了到内建循环垃圾收集器的接口.2313 Python 使用引用记数来跟踪什么时候销毁一个对象; 一个对象的最后一个引用2314 一旦消失, 这个对象就会被销毁.2315 从 2.0版开始, Python 还提供了一个循环垃圾收集器, 它每隔一段时间执行.2316 这个收集器查找指向自身的数据结构, 并尝试破坏循环. 如 Example 1-87所2317 示.2318 你可以使用 gc.collect 函数来强制完整收集. 这个函数将返回收集器销毁的2319 对象的数量.2320 1.17.0.1. Example 1-87. 使用 gc 模块收集循环引用垃圾2321 File: gc-example-1.py2322 importgc2323 #create a simple object that links to itself

2324 classNode:2325 def_ _init_ _(self, name):2326 self.name =name2327 self.parent =None2328 self.children =[]2329 defaddchild(self, node):2330 node.parent =self2331 self.children.append(node)2332 def_ _repr_ _(self):2333 return "" %(repr(self.name), id(self))2334 #set up a self-referencing structure

2335 root = Node("monty")2336 root.addchild(Node("eric"))2337 root.addchild(Node("john"))2338 root.addchild(Node("michael"))2339 #remove our only reference

2340 delroot2341 print gc.collect(), "unreachable objects"

2342 print gc.collect(), "unreachable objects"

2343 12unreachable objects2344 0 unreachable objects2345 如果你确定你的程序不会创建自引用的数据结构, 你可以使用 gc.disable 函2346 数禁用垃圾收集, 调用这个函数以后, Python 的工作方式将与 1.5.2或更早2347 的版本相同.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值