Python标准库

体元主人

贡献于2011-02-23

字数:0 关键词: 标准库 Python开发 Python

Python Standard Library 翻译: Python 江湖群 10/06/07 20:10:08 编译 • 0.1. 关于本书 • 0.2. 代码约定 • 0.3. 关于例子 • 0.4. 如何联系我们 1. 核心模块 o 1.1. 介绍 o 1.2. _ _builtin_ _ 模块 o 1.3. exceptions 模块 o 1.4. os 模块 o 1.5. os.path 模块 o 1.6. stat 模块 o 1.7. string 模块 o 1.8. re 模块 o 1.9. math 模块 o 1.10. cmath 模块 o 1.11. operator 模块 o 1.12. copy 模块 o 1.13. sys 模块 o 1.14. atexit 模块 o 1.15. time 模块 o 1.16. types 模块 o 1.17. gc 模块 2. 更多标准模块 o 2.1. 概览 o 2.2. fileinput 模块 o 2.3. shutil 模块 o 2.4. tempfile 模块 o 2.5. StringIO 模块 o 2.6. cStringIO 模块 o 2.7. mmap 模块 o 2.8. UserDict 模块 o 2.9. UserList 模块 o 2.10. UserString 模块 o 2.11. traceback 模块 o 2.12. errno 模块 o 2.13. getopt 模块 o 2.14. getpass 模块 o 2.15. glob 模块 o 2.16. fnmatch 模块 o 2.17. random 模块 o 2.18. whrandom 模块 o 2.19. md5 模块 o 2.20. sha 模块 o 2.21. crypt 模块 o 2.22. rotor 模块 o 2.23. zlib 模块 o 2.24. code 模块 3. 线程和进程 o 3.1. 概览 o 3.2. threading 模块 o 3.3. Queue 模块 o 3.4. thread 模块 o 3.5. commands 模块 o 3.6. pipes 模块 o 3.7. popen2 模块 o 3.8. signal 模块 4. 数据表示 o 4.1. 概览 o 4.2. array 模块 o 4.3. struct 模块 o 4.4. xdrlib 模块 o 4.5. marshal 模块 o 4.6. pickle 模块 o 4.7. cPickle 模块 o 4.8. copy_reg 模块 o 4.9. pprint 模块 o 4.10. repr 模块 o 4.11. base64 模块 o 4.12. binhex 模块 o 4.13. quopri 模块 o 4.14. uu 模块 o 4.15. binascii 模块 5. 文件格式 o 5.1. 概览 o 5.2. xmllib 模块 o 5.3. xml.parsers.expat 模块 o 5.4. sgmllib 模块 o 5.5. htmllib 模块 o 5.6. htmlentitydefs 模块 o 5.7. formatter 模块 o 5.8. ConfigParser 模块 o 5.9. netrc 模块 o 5.10. shlex 模块 o 5.11. zipfile 模块 o 5.12. gzip 模块 6. 邮件和新闻消息处理 o 6.1. 概览 o 6.2. rfc822 模块 o 6.3. mimetools 模块 o 6.4. MimeWriter 模块 o 6.5. mailbox 模块 o 6.6. mailcap 模块 o 6.7. mimetypes 模块 o 6.8. packmail 模块 o 6.9. mimify 模块 o 6.10. multifile 模块 7. 网络协议 o 7.1. 概览 o 7.2. socket 模块 o 7.3. select 模块 o 7.4. asyncore 模块 o 7.5. asynchat 模块 o 7.6. urllib 模块 o 7.7. urlparse 模块 o 7.8. cookie 模块 o 7.9. robotparser 模块 o 7.10. ftplib 模块 o 7.11. gopherlib 模块 o 7.12. httplib 模块 o 7.13. poplib 模块 o 7.14. imaplib 模块 o 7.15. smtplib 模块 o 7.16. telnetlib 模块 o 7.17. nntplib 模块 o 7.18. SocketServer 模块 o 7.19. BaseHTTPServer 模块 o 7.20. SimpleHTTPServer 模块 o 7.21. CGIHTTPServer 模块 o 7.22. cgi 模块 o 7.23. webbrowser 模块 8. 国际化 o 8.1. locale 模块 o 8.2. unicodedata 模块 o 8.3. ucnhash 模块 9. 多媒体相关模块 o 9.1. 概览 o 9.2. imghdr 模块 o 9.3. sndhdr 模块 o 9.4. whatsound 模块 o 9.5. aifc 模块 o 9.6. sunau 模块 o 9.7. sunaudio 模块 o 9.8. wave 模块 o 9.9. audiodev 模块 o 9.10. winsound 模块 10.数据储存 o 10.1. 概览 o 10.2. anydbm 模块 o 10.3. whichdb 模块 o 10.4. shelve 模块 o 10.5. dbhash 模块 o 10.6. dbm 模块 o 10.7. dumbdbm 模块 o 10.8. gdbm 模块 11.工具和实用程序 o 11.1. dis 模块 o 11.2. pdb 模块 o 11.3. bdb 模块 o 11.4. profile 模块 o 11.5. pstats 模块 o 11.6. tabnanny 模块 12.其他模块 o 12.1. 概览 o 12.2. fcntl 模块 o 12.3. pwd 模块 o 12.4. grp 模块 o 12.5. nis 模块 o 12.6. curses 模块 o 12.7. termios 模块 o 12.8. tty 模块 o 12.9. resource 模块 o 12.10. syslog 模块 o 12.11. msvcrt 模块 o 12.12. nt 模块 o 12.13. _winreg 模块 o 12.14. posix 模块 13.执行支持模块 o 13.1. dospath 模块 o 13.2. macpath 模块 o 13.3. ntpath 模块 o 13.4. posixpath 模块 o 13.5. strop 模块 o 13.6. imp 模块 o 13.7. new 模块 o 13.8. pre 模块 o 13.9. sre 模块 o 13.10. py_compile 模块 o 13.11. compileall 模块 o 13.12. ihooks 模块 o 13.13. linecache 模块 o 13.14. macurl2path 模块 o 13.15. nturl2path 模块 o 13.16. tokenize 模块 o 13.17. keyword 模块 o 13.18. parser 模块 o 13.19. symbol 模块 o 13.20. token 模块 14.其他模块 o 14.1. 概览 o 14.2. pyclbr 模块 o 14.3. filecmp 模块 o 14.4. cmd 模块 o 14.5. rexec 模块 o 14.6. Bastion 模块 o 14.7. readline 模块 o 14.8. rlcompleter 模块 o 14.9. statvfs 模块 o 14.10. calendar 模块 o 14.11. sched 模块 o 14.12. statcache 模块 o 14.13. grep 模块 o 14.14. dircache 模块 o 14.15. dircmp 模块 o 14.16. cmp 模块 o 14.17. cmpcache 模块 o 14.18. util 模块 o 14.19. soundex 模块 o 14.20. timing 模块 o 14.21. posixfile 模块 o 14.22. bisect 模块 o 14.23. knee 模块 o 14.24. tzparse 模块 o 14.25. regex 模块 o 14.26. regsub 模块 o 14.27. reconvert 模块 o 14.28. regex_syntax 模块 o 14.29. find 模块 15.Py 2.0 后新增模块 16.后记 "We'd like to pretend that 'Fredrik' is a role, but even hundreds of volunteers couldn't possibly keep up. No, 'Fredrik' is the result of crossing an http server with a spam filter with an emacs whatsit and some other stuff besides." -Gordon McMillan, June 1998 Python 2.0 发布附带了一个包含 200 个以上模块的可扩展的标准库. 本书简要 地介绍每个模块并提供至少一个例子来说明如何使用它. 本书一共包含 360 个 例子. 0.1. 关于本书 "Those people who have nothing better to do than post on the Internet all day long are rarely the ones who have the most insights." - Jakob Nielsen, December 1998 五年前我偶然遇到了 Python, 开始了我的 Python 之旅, 我花费了大量的时间 在 comp.lang.python 新闻组里回答问题. 也许某个人发现一个模块正是他想 要的, 但是却不知道如何使用它. 也许某个人为他的任务挑选的不合适的模块. 也许某个人已经厌倦了发明新轮子. 大多时候, 一个简短的例子要比一份手册 文档更有帮助. 本书是超过 3,000 个新闻组讨论的精华部分, 当然也有很多的新脚本, 为了涵 盖标准库的每个角落. 我尽力使得每个脚本都易于理解, 易于重用代码. 我有意缩短注释的长度, 如 果你想更深入地了解背景, 那么你可以参阅每个 Python 发布中的参考手册. 本书的重要之处在于范例代码. 我们欢迎任何评论, 建议, 以及 bug 报告, 请将它们发送到 fredrik@pythonware.com . 我将阅读尽我所能阅读所有的邮件, 但可能回复不 是那么及时. 本书的相关更新内容以及其他信息请访问 http://www.pythonware.com/people/fredrik/librarybook.htm 为什么没有 Tkinter? 本书涵盖了整个标准库, 除了(可选的)Tkinter ui(user-interface : 用户界面) 库. 有很多原因, 更多是因为时间, 本书的空间, 以及我正在写另一本关于 Tkinter 的书. 关于这些书的信息, 请访问 http://www.pythonware.com/people/fredrik/tkinterbook.htm . (不用看了, 又一 404) 产品细节 本书使用 DocBook SGML 编写, 我使用了一系列的工具, 包括 Secret Labs' PythonWorks, Excosoft Documentor, James Clark's Jade DSSSL processor, Norm Walsh's DocBook stylesheets, 当然,还有一些 Python 脚本. 感谢帮忙校对的人们: Tim Peters, Guido van Rossum, David Ascher, Mark Lutz, 和 Rael Dornfest, 以及 PythonWare 成员: Matthew Ellis, H?kan Karlsson, 和 Rune Uhlin. 感谢 Lenny Muellner, 他帮助我把 SGML 文件转变为你们现在所看到的这本书, 以及 Christien Shangraw, 他将那些代码文件集合起来做成了随书 CD (可以在 http://examples.oreilly.com/pythonsl 找到, 竟然没有 404, 奇迹). 0.2. 代码约定 本书使用以下习惯用法: 斜体 用于文件名和命令. 还用于定义术语. 等宽字体 e.g. Python 用于代码以及方法,模块,操作符,函数,语句,属性等的名称. 等宽粗体 用于代码执行结果. 0.3. 关于例子 除非提到,所有例子都可以在 Python 1.5.2 和 Python 2.0 下运行. 能不能在 Python 2.4/2.5 下执行.....看参与翻译各位的了. 除了一些平台相关模块的脚本, 所有例子都可以在 Windows, Solaris, 以及 Linux 下正常执行. 所有代码都是有版权的. 当然,你可以自由地使用这些这些模块,别忘记你是从 哪得到(?学会)这些的. 大多例子的文件名都包含它所使用的模块名称,后边是 "-example- " 以及一个 唯一的"序号". 注意有些例子并不是按顺序出现的, 这是为了匹配本书的较早 版本 - (the eff-bot guide to) The Standard Python Library . 你可以在网上找到本书附带 CD 的内容 (参阅 http://examples.oreilly.com/pythonsl ). 更多信息以及更新内容参阅 http://www.pythonware.com/people/fredrik/librarybook.htm . (ft, 又一 404. 大家一定不要看~) 0.4. 如何联系我们 Python 江湖 QQ 群: 43680167 Feather (校对) QQ: 85660100 1. 核心模块 "Since the functions in the C runtime library are not part of the Win32 API, we believe the number of applications that will be affected by this bug to be very limited." - Microsoft, January 1999 1.1. 介绍 Python 的标准库包括了很多的模块, 从 Python 语言自身特定的类型和声明, 到一些只用于少数程序的不著名的模块. 本章描述了一些基本的标准库模块. 任何大型 Python 程序都有可能直接或间 接地使用到这类模块的大部分. 1.1.1. 内建函数和异常 下面的这两个模块比其他模块加在一起还要重要: 定义内建函数(例如 len, int, range ...)的 _ _builtin_ _ 模块, 以及定义所有内建异常的 exceptions 模块. Python 在启动时导入这两个模块, 使任何程序都能够使用它们. 1.1.2. 操作系统接口模块 Python 有许多使用了 POSIX 标准 API 和标准 C 语言库的模块. 它们为底层 操作系统提供了平台独立的接口. 这类的模块包括: 提供文件和进程处理功能的 os 模块; 提供平台独立的文件 名处理 (分拆目录名, 文件名, 后缀等)的 os.path 模块; 以及时间日期处理 相关的 time/datetime 模块. [!Feather 注: datetime 为 Py2.3 新增模块, 提供增强的时间处理方法 ] 延伸一点说, 网络和线程模块同样也可以归为这一个类型. 不过 Python 并没 有在所有的平台/版本实现这些. 1.1.3. 类型支持模块 标准库里有许多用于支持内建类型操作的库. string 模块实现了常用的字符串 处理. math 模块提供了数学计算操作和常量(pi, e都属于这类常量), cmath 模 块为复数提供了和 math 一样的功能. 1.1.4. 正则表达式 re 模块为 Python 提供了正则表达式支持. 正则表达式是用于匹配字符串或特 定子字符串的有特定语法的字符串模式. 1.1.5. 语言支持模块 sys 模块可以让你访问解释器相关参数,比如模块搜索路径,解释器版本号等. operator 模块提供了和内建操作符作用相同的函数. copy 模块允许你复制对 象, Python 2.0 新加入的 gc 模块提供了对垃圾收集的相关控制功能. 1.2. _ _builtin_ _ 模块 这个模块包含 Python 中使用的内建函数. 一般不用手动导入这个模块; Python 会帮你做好一切. 1.2.1. 使用元组或字典中的参数调用函数 Python 允许你实时地创建函数参数列表. 只要把所有的参数放入一个元组中, 然后通过内建的 apply 函数调用函数. 如 Example 1-1 . 1.2.1.1. Example 1-1. 使用 apply 函数 File: builtin-apply-example-1.py def function(a, b): print a, b apply(function, ("whither", "canada?")) apply(function, (1, 2 + 3)) whither canada? 1 5 要想把关键字参数传递给一个函数, 你可以将一个字典作为 apply 函数的第 3 个参数, 参考 Example 1-2 . 1.2.1.2. Example 1-2. 使用 apply 函数传递关键字参数 File: builtin-apply-example-2.py def function(a, b): print a, b apply(function, ("crunchy", "frog")) apply(function, ("crunchy",), {"b": "frog"}) apply(function, (), {"a": "crunchy", "b": "frog"}) crunchy frog crunchy frog crunchy frog apply 函数的一个常见用法是把构造函数参数从子类传递到基类, 尤其是构造 函数需要接受很多参数的时候. 如 Example 1-3 所示. 1.2.1.3. Example 1-3. 使用 apply 函数调用基类的构造函数 File: builtin-apply-example-3.py class Rectangle: def _ _init_ _(self, color="white", width=10, height=10): print "create a", color, self, "sized", width, "x", height class RoundedRectangle(Rectangle): def _ _init_ _(self, **kw): apply(Rectangle._ _init_ _, (self,), kw) rect = Rectangle(color="green", height= 100, width=100) rect= RoundedRectangle(color= "blue", height = 20)< /FONT> < FONT face= 宋体> create a green sized 100 x 100 create a blue sized 10 x 20 Python 2.0 提供了另个方法来做相同的事. 你只需要使用一个传统的函数调 用 , 使用 * 来标记元组, ** 来标记字典. 下面两个语句是等价的: result = function(*args, **kwargs) result = apply(function, args, kwargs) < /FONT > 1.2.2. 加载和重载模块 如果你写过较庞大的 Python 程序, 那么你就应该知道 import 语句是用来导 入外部模块的 (当然也可以使用 from-import 版本). 不过你可能不知道 import 其实是靠调用内建函数 _ _import_ _ 来工作的. 通过这个戏法你可以动态地调用函数. 当你只知道模块名称(字符串)的时候, 这将很方便. Example 1-4 展示了这种用法, 动态地导入所有以 "-plugin " 结 尾的模块. 1.2.2.1. Example 1-4. 使用 _ _import_ _ 函数加载模块 File: builtin-import-example-1.py import glob, os modules = [] for module_file in glob.glob("*-plugin.py"): try: module_name, ext = os.path.splitext(os.path.basename(module_file)) module = _ _import_ _(module_name) modules.append(module) except ImportError: pass # ignore broken modules # say hello to all modules for module in modules: module.hello() example-plugin says hello 注意这个 plug-in 模块文件名中有个 "-" (hyphens). 这意味着你不能使用普 通的 import 命令, 因为 Python 的辨识符不允许有 "-" . Example 1-5 展示了 Example 1-4 中使用的 plug-in . 1.2.2.2. Example 1-5. Plug-in 例子 File: example-plugin.py def hello(): print "example-plugin says hello" Example 1-6 展示了如何根据给定模块名和函数名获得想要的函数对象. 1.2.2.3. Example 1-6. 使用 _ _import_ _ 函数获得特定函数 File: builtin-import-example-2.py def getfunctionbyname(module_name, function_name): module = _ _import_ _(module_name) return getattr(module, function_name) print repr(getfunctionbyname("dumbdbm", "open")) 你也可以使用这个函数实现延迟化的模块导入 (lazy module loading). 例如在 Example 1-7 中的 string 模块只在第一次使用的时候导入. 1.2.2.4. Example 1-7. 使用 _ _import_ _ 函数实现 延迟导入 File: builtin-import-example-3.py class LazyImport: def _ _init_ _(self, module_name): self.module_name = module_name self.module = None def _ _getattr_ _(self, name): if self.module is None: self.module = _ _import_ _(self.module_name) return getattr(self.module, name) string = LazyImport("string") print string.lowercase abcdefghijklmnopqrstuvwxyz Python 也提供了重新加载已加载模块的基本支持. [Example 1-8 #eg-1-8 会加 载 3 次 hello.py 文件. 1.2.2.5. Example 1-8. 使用 reload 函数 File: builtin-reload-example-1.py import hello reload(hello) reload(hello) hello again, and welcome to the show hello again, and welcome to the show hello again, and welcome to the show reload 直接接受模块作为参数. [!Feather 注: ^ 原句无法理解, 稍后讨论.] 注意,当你重加载模块时, 它会被重新编译, 新的模块会代替模块字典里的老模 块. 但是, 已经用原模块里的类建立的实例仍然使用的是老模块(不会被更新). 同样地, 使用 from-import 直接创建的到模块内容的引用也是不会被更新的. 1.2.3. 关于名称空间 dir 返回由给定模块, 类, 实例, 或其他类型的所有成员组成的列表. 这可能 在交互式 Python 解释器下很有用, 也可以用在其他地方. Example 1-9 展示了 dir 函数的用法. 1.2.3.1. Example 1-9. 使用 dir 函数 File: builtin-dir-example-1.py def dump(value): print value, "=>", dir(value) import sys dump(0) dump(1.0) dump(0.0j) # complex number dump([]) # list dump({}) # dictionary dump("string") dump(len) # function dump(sys) # module 0 => [] 1.0 => [] 0j => ['conjugate', 'imag', 'real'] [] => ['append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] {} => ['clear', 'copy', 'get', 'has_key', 'items', 'keys', 'update', 'values'] string = > [] = > ['_ _doc_ _', '_ _name_ _', '_ _self_ _'] = > ['_ _doc_ _', '_ _name_ _', '_ _stderr_ _', '_ _stdin_ _', '_ _stdout_ _', 'argv', 'builtin_module_names', 'copyright', 'dllhandle', 'exc_info', 'exc_type', 'exec_prefix', 'executable', ... 在例子 Example 1-10 中定义的 getmember 函数返回给定类定义的所有类级别 的属性和方法. 1.2.3.2. Example 1-10. 使用 dir 函数查找类的所有成员 File: builtin-dir-example-2.py class A: def a(self): pass def b(self): pass class B(A): def c(self): pass def d(self): pass def getmembers(klass, members=None): # get a list of all class members, ordered by class if members is None: members = [] for k in klass._ _bases_ _: getmembers(k, members) for m in dir(klass): if m not in members: members.append(m) return members print getmembers(A) print getmembers(B) print getmembers(IOError) < FONT face= 宋体 > ['_ _doc_ _', '_ _module_ _', 'a', 'b'] ['_ _doc_ _', '_ _module_ _', 'a', 'b', 'c', 'd'] ['_ _doc_ _', '_ _getitem_ _', '_ _init_ _', '_ _module_ _', '_ _str_ _'] getmembers 函数返回了一个有序列表. 成员在列表中名称出现的越早, 它所处 的类层次就越高. 如果无所谓顺序的话, 你可以使用字典代替列表. [!Feather 注: 字典是无序的, 而列表和元组是有序的, 网上有关于有序字典 的讨论] vars 函数与此相似, 它返回的是包含每个成员当前值的字典. 如果你使用不带 参数的 vars , 它将返回当前局部名称空间的可见元素(同 locals() 函数 ). 如 Example 1-11 所表示. 1.2.3.3. Example 1-11. 使用 vars 函数 File: builtin-vars-example-1.py book = "library2" pages = 250 scripts = 350 print "the %(book)s book contains more than %(scripts)s scripts" % vars() the library book contains more than 350 scripts 1.2.4. 检查对象类型 Python 是一种动态类型语言, 这意味着给一个定变量名可以在不同的场合绑定 到不同的类型上. 在接下面例子中, 同样的函数分别被整数, 浮点数, 以及一 个字符串调用: def function(value): print value function(1) function(1.0) function("one") type 函数 (如 Example 1-12 所示) 允许你检查一个变量的类型. 这个函数会 返回一个 type descriptor (类型描述符) , 它对于 Python 解释器提供的每个 类型都是不同的. 1.2.4.1. Example 1-12. 使用 type 函数 File: builtin-type-example-1.py def dump(value): print type(value), value dump(1) dump(1.0) dump("one") 1 1.0 one 每个类型都有一个对应的类型对象, 所以你可以使用 is 操作符 (对象身份?) 来检查类型. (如 Example 1-13 所示). 1.2.4.2. Example 1-13. 对文件名和文件对象使用 type 函数 File: builtin-type-example-2.py def load(file): if isinstance(file, type("")): file = open(file, "rb") return file.read() print len(load("samples/sample.jpg")), "bytes" print len(load(open("samples/sample.jpg", "rb"))), "bytes" 4672 bytes 4672 bytes callable 函数, 如 Example 1-14 所示, 可以检查一个对象是否是可调用的 (无论是直接调用或是通过 apply ). 对于函数, 方法, lambda 函式, 类, 以及 实现了 _ _call_ _ 方法的类实例, 它都返回 True. 1.2.4.3. Example 1-14. 使用 callable 函数 File: builtin-callable-example-1.py def dump(function): if callable(function): print function, "is callable" else: print function, "is *not* callable" class A: def method(self, value): return value class B(A): def _ _call_ _(self, value): return value a = A() b = B() dump(0) # simple objects dump("string") dump(callable) dump(dump) # function dump(A) # classes dump(B) dump(B.method) dump(a) # instances dump(b) dump(b.method) < FONT face = 宋体 > 0 is *not* callable string is *not* callable is callable is callable A is callable B is callable is callable is *not* callable is callable is callable 注意类对象 (A 和 B) 都是可调用的; 如果调用它们, 就产生新的对象(类实 例). 但是 A 类的实例不可调用, 因为它的类没有实现 _ _call_ _ 方法. 你可以在 operator 模块中找到检查对象是否为某一内建类型(数字, 序列, 或 者字典等) 的函数. 但是, 因为创建一个类很简单(比如实现基本序列方法的 类), 所以对这些类型使用显式的类型判断并不是好主意. 在处理类和实例的时候会复杂些. Python 不会把类作为本质上的类型对待; 相 反地, 所有的类都属于一个特殊的类类型(special class type), 所有的类实例 属于一个特殊的实例类型(special instance type). 这意味着你不能使用 type 函数来测试一个实例是否属于一个给定的类; 所有 的实例都是同样的类型! 为了解决这个问题, 你可以使用 isinstance 函数,它 会检查一个对象是不是给定类(或其子类)的实例. Example 1-15 展示了 isinstance 函数的使用. 1.2.4.4. Example 1-15. 使用 isinstance 函数 File: builtin-isinstance-example-1.py class A: pass class B: pass class C(A): pass class D(A, B): pass def dump(object): print object, "=>", if isinstance(object, A): print "A", if isinstance(object, B): print "B", if isinstance(object, C): print "C", if isinstance(object, D): print "D", print a = A() b = B() c= C() d = D() dump(a) dump(b) dump(c) dump(d) dump(0) dump("string")< /FONT > < FONT face = 宋体 > => A => B = > A C = > A B D 0 = > string = > issubclass 函数与此相似, 它用于检查一个类对象是否与给定类相同, 或者是 给定类的子类. 如 Example 1-16 所示. 注意, isinstance 可以接受任何对象作为参数, 而 issubclass 函数在接受非 类对象参数时会引发 TypeError 异常. 1.2.4.5. Example 1-16. 使用 issubclass 函数 File: builtin-issubclass-example-1.py class A: pass class B: pass class C(A): pass class D(A, B): pass def dump(object): print object, "=>", if issubclass(object, A): print "A", if issubclass(object, B): print "B", if issubclass(object, C): print "C", if issubclass(object, D): print "D", print dump(A) dump(B) dump(C) dump(D) dump(0) dump("string") A => A B => B C => A C D = > A B D 0 = > Traceback (innermost last): File "builtin-issubclass-example-1.py", line 29, in ? File "builtin-issubclass-example-1.py", line 15, in dump TypeError: arguments must be classes 1.2.5. 计算 Python 表达式 Python 提供了在程序中与解释器交互的多种方法. 例如 eval 函数将一个字符 串作为 Python 表达式求值. 你可以传递一串文本, 简单的表达式, 或者使用 内建 Python 函数. 如 Example 1-17 所示. 1.2.5.1. Example 1-17. 使用 eval 函数 File: builtin-eval-example-1.py def dump(expression): result = eval(expression) print expression, "=>", result, type(result) dump("1") dump("1.0") dump("'string'") dump("1.0 + 2.0") dump("'*' * 10") dump("len('world')") < FONT face = 宋体> 1 => 1 1.0 => 1.0 'string' = > string 1.0 + 2.0 = > 3.0 '*' * 10= > ********** len('world')= > 5 如果你不确定字符串来源的安全性, 那么你在使用 eval 的时候会遇到些麻烦. 例如, 某个用户可能会使用 _ _import_ _ 函数加载 os 模块, 然后从硬盘删除 文件 (如 Example 1-18 所示). 1.2.5.2. Example 1-18. 使用 eval 函数执行任意命令 File: builtin-eval-example-2.py print eval("_ _import_ _('os').getcwd()") print eval("_ _import_ _('os').remove('file')") /home/fredrik/librarybook Traceback (innermost last): File "builtin-eval-example-2", line 2, in ? File"", line 0, in ? os.error: (2, 'No such file or directory') 这里我们得到了一个 os.error 异常, 这说明 Python 事实上在尝试删除文件! 幸运地是, 这个问题很容易解决. 你可以给 eval 函数传递第 2 个参数, 一个 定义了该表达式求值时名称空间的字典. 我们测试下, 给函数传递个空字典: >>> print eval("_ _import_ _('os').remove('file')", {}) Traceback (innermost last):File "", line 1, in ? File"", line 0, in ? os.error: (2, 'No such file or directory') 呃.... 我们还是得到了个 os.error 异常. 这是因为 Python 在求值前会检查这个字典, 如果没有发现名称为 _ _builtins_ _ 的变量(复数形式), 它就会添加一个: >>> namespace = {} >>> print eval("_ _import_ _('os').remove('file')", namespace) Traceback (innermost last): File "",line 1, in ? File "", line0, in ? os.error: (2, 'No such file or directory') >>> namespace.keys() ['_ _builtins_ _'] < /FONT > 如果你打印这个 namespace 的内容, 你会发现里边有所有的内建函数. [!Feather 注: 如果我 RP 不错的话, 添加的这个_ _builtins_ _就是当前的_ _builtins_ _] 我们注意到了如果这个变量存在, Python 就不会去添加默认的, 那么我们的解 决方法也来了, 为传递的字典参数加入一个 _ _builtins_ _ 项即可. 如 Example 1-19 所示. 1.2.5.3. Example 1-19. 安全地使用 eval 函数求值 File: builtin-eval-example-3.py print eval("_ _import_ _('os').getcwd()", {}) print eval("_ _import_ _('os').remove('file')", {"_ _builtins_ _": {}}) /home/fredrik/librarybook Traceback (innermost last): File "builtin-eval-example-3.py", line 2, in ? File"", line 0, in ? NameError: _ _import_ _ 即使这样, 你仍然无法避免针对 CPU 和内存资源的攻击. (比如, 形如 eval("'*'*1000000*2*2*2*2*2*2*2*2*2") 的语句在执行后会使你的程序耗尽 系统资源). 1.2.6. 编译和执行代码 eval 函数只针对简单的表达式. 如果要处理大块的代码, 你应该使用 compile 和 exec 函数 (如 Example 1-20 所示). 1.2.6.1. Example 1-20. 使用 compile 函数检查语法 File: builtin-compile-example-1.py NAME = "script.py" BODY = """ prnt 'owl-stretching time' """ try: compile(BODY, NAME, "exec") except SyntaxError, v: print "syntax error:", v, "in", NAME # syntax error: invalid syntax in script.py < /FONT > 成功执行后, compile 函数会返回一个代码对象, 你可以使用 exec 语句执行 它, 参见 Example 1-21 . 1.2.6.2. Example 1-21. 执行已编译的代码 File: builtin-compile-example-2.py BODY = """ print 'the ant, an introduction' """ code = compile(BODY,"