Python菜鸟学习手册14----标准库+代码实例


Python Standard Library

翻译: Python 江湖群

10/06/07 20:10:08 编译


  • 0.1. 关于本书
  • 0.2. 代码约定
  • 0.3. 关于例子
  • 0.4. 如何联系我们
  1. 核心模块
    • 1.1. 介绍
    • 1.2. _ _builtin_ _ 模块
    • 1.3. exceptions 模块
    • 1.4. os 模块
    • 1.5. os.path 模块
    • 1.6. stat 模块
    • 1.7. string 模块
    • 1.8. re 模块
    • 1.9. math 模块
    • 1.10. cmath 模块
    • 1.11. operator 模块
    • 1.12. copy 模块
    • 1.13. sys 模块
    • 1.14. atexit 模块
    • 1.15. time 模块
    • 1.16. types 模块
    • 1.17. gc 模块
  2. 更多标准模块
    • 2.1. 概览
    • 2.2. fileinput 模块
    • 2.3. shutil 模块
    • 2.4. tempfile 模块
    • 2.5. StringIO 模块
    • 2.6. cStringIO 模块
    • 2.7. mmap 模块
    • 2.8. UserDict 模块
    • 2.9. UserList 模块
    • 2.10. UserString 模块
    • 2.11. traceback 模块
    • 2.12. errno 模块
    • 2.13. getopt 模块
    • 2.14. getpass 模块
    • 2.15. glob 模块
    • 2.16. fnmatch 模块
    • 2.17. random 模块
    • 2.18. whrandom 模块
    • 2.19. md5 模块
    • 2.20. sha 模块
    • 2.21. crypt 模块
    • 2.22. rotor 模块
    • 2.23. zlib 模块
    • 2.24. code 模块
  3. 线程和进程
    • 3.1. 概览
    • 3.2. threading 模块
    • 3.3. Queue 模块
    • 3.4. thread 模块
    • 3.5. commands 模块
    • 3.6. pipes 模块
    • 3.7. popen2 模块
    • 3.8. signal 模块
  4. 数据表示
    • 4.1. 概览
    • 4.2. array 模块
    • 4.3. struct 模块
    • 4.4. xdrlib 模块
    • 4.5. marshal 模块
    • 4.6. pickle 模块
    • 4.7. cPickle 模块
    • 4.8. copy_reg 模块
    • 4.9. pprint 模块
    • 4.10. repr 模块
    • 4.11. base64 模块
    • 4.12. binhex 模块
    • 4.13. quopri 模块
    • 4.14. uu 模块
    • 4.15. binascii 模块
  5. 文件格式
    • 5.1. 概览
    • 5.2. xmllib 模块
    • 5.3. xml.parsers.expat 模块
    • 5.4. sgmllib 模块
    • 5.5. htmllib 模块
    • 5.6. htmlentitydefs 模块
    • 5.7. formatter 模块
    • 5.8. ConfigParser 模块
    • 5.9. netrc 模块
    • 5.10. shlex 模块
    • 5.11. zipfile 模块
    • 5.12. gzip 模块
  6. 邮件和新闻消息处理
    • 6.1. 概览
    • 6.2. rfc822 模块
    • 6.3. mimetools 模块
    • 6.4. MimeWriter 模块
    • 6.5. mailbox 模块
    • 6.6. mailcap 模块
    • 6.7. mimetypes 模块
    • 6.8. packmail 模块
    • 6.9. mimify 模块
    • 6.10. multifile 模块
  7. 网络协议
    • 7.1. 概览
    • 7.2. socket 模块
    • 7.3. select 模块
    • 7.4. asyncore 模块
    • 7.5. asynchat 模块
    • 7.6. urllib 模块
    • 7.7. urlparse 模块
    • 7.8. cookie 模块
    • 7.9. robotparser 模块
    • 7.10. ftplib 模块
    • 7.11. gopherlib 模块
    • 7.12. httplib 模块
    • 7.13. poplib 模块
    • 7.14. imaplib 模块
    • 7.15. smtplib 模块
    • 7.16. telnetlib 模块
    • 7.17. nntplib 模块
    • 7.18. SocketServer 模块
    • 7.19. BaseHTTPServer 模块
    • 7.20. SimpleHTTPServer 模块
    • 7.21. CGIHTTPServer 模块
    • 7.22. cgi 模块
    • 7.23. webbrowser 模块
  8. 国际化
    • 8.1. locale 模块
    • 8.2. unicodedata 模块
    • 8.3. ucnhash 模块
  9. 多媒体相关模块
    • 9.1. 概览
    • 9.2. imghdr 模块
    • 9.3. sndhdr 模块
    • 9.4. whatsound 模块
    • 9.5. aifc 模块
    • 9.6. sunau 模块
    • 9.7. sunaudio 模块
    • 9.8. wave 模块
    • 9.9. audiodev 模块
    • 9.10. winsound 模块
  10. 数据储存
    • 10.1. 概览
    • 10.2. anydbm 模块
    • 10.3. whichdb 模块
    • 10.4. shelve 模块
    • 10.5. dbhash 模块
    • 10.6. dbm 模块
    • 10.7. dumbdbm 模块
    • 10.8. gdbm 模块
  11. 工具和实用程序
    • 11.1. dis 模块
    • 11.2. pdb 模块
    • 11.3. bdb 模块
    • 11.4. profile 模块
    • 11.5. pstats 模块
    • 11.6. tabnanny 模块
  12. 其他模块
    • 12.1. 概览
    • 12.2. fcntl 模块
    • 12.3. pwd 模块
    • 12.4. grp 模块
    • 12.5. nis 模块
    • 12.6. curses 模块
    • 12.7. termios 模块
    • 12.8. tty 模块
    • 12.9. resource 模块
    • 12.10. syslog 模块
    • 12.11. msvcrt 模块
    • 12.12. nt 模块
    • 12.13. _winreg 模块
    • 12.14. posix 模块
  13. 执行支持模块
    • 13.1. dospath 模块
    • 13.2. macpath 模块
    • 13.3. ntpath 模块
    • 13.4. posixpath 模块
    • 13.5. strop 模块
    • 13.6. imp 模块
    • 13.7. new 模块
    • 13.8. pre 模块
    • 13.9. sre 模块
    • 13.10. py_compile 模块
    • 13.11. compileall 模块
    • 13.12. ihooks 模块
    • 13.13. linecache 模块
    • 13.14. macurl2path 模块
    • 13.15. nturl2path 模块
    • 13.16. tokenize 模块
    • 13.17. keyword 模块
    • 13.18. parser 模块
    • 13.19. symbol 模块
    • 13.20. token 模块
  14. 其他模块
    • 14.1. 概览
    • 14.2. pyclbr 模块
    • 14.3. filecmp 模块
    • 14.4. cmd 模块
    • 14.5. rexec 模块
    • 14.6. Bastion 模块
    • 14.7. readline 模块
    • 14.8. rlcompleter 模块
    • 14.9. statvfs 模块
    • 14.10. calendar 模块
    • 14.11. sched 模块
    • 14.12. statcache 模块
    • 14.13. grep 模块
    • 14.14. dircache 模块
    • 14.15. dircmp 模块
    • 14.16. cmp 模块
    • 14.17. cmpcache 模块
    • 14.18. util 模块
    • 14.19. soundex 模块
    • 14.20. timing 模块
    • 14.21. posixfile 模块
    • 14.22. bisect 模块
    • 14.23. knee 模块
    • 14.24. tzparse 模块
    • 14.25. regex 模块
    • 14.26. regsub 模块
    • 14.27. reconvert 模块
    • 14.28. regex_syntax 模块
    • 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 报告, 请将它们发送到 [email protected]. 我将阅读尽我所能阅读所有的邮件, 但可能回复不是那么及时.

本书的相关更新内容以及其他信息请访问 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)

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)

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)

['_ _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)

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")

 => 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')")

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 "", line 0, in ?
os.error: (2, 'No such file or directory')
>>> namespace.keys()
['_ _builtins_ _']

如果你打印这个 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

成功执行后, 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, "
                    
                    

你可能感兴趣的:(Python,python,标准库)