Python 标准库

PythonStandardLibrary

Python 2.0发布附带了一个包含200个以上模块的可扩展的标准库本书简要地介绍每个模块并提供至少一个例子来说明如何使用它. 本书一共包含360个例子.

目录:
          关于本书
          代码约定
          关于例子
          如何联系我们
          核心模块
          介绍
          内建函数和异常
          操作系统接口模块
          类型支持模块
          正则表达式
          语言支持模块
  _ _builtin_ _ 模块
          使用元组或字典中的参数调用函数
                  使用 apply 函数
                  使用 apply 函数传递关键字参数
                  使用 apply 函数调用基类的构造函数
          加载和重载模块
                  使用 _ _import_ _ 函数加载模块
                  Plug-in 例子
                  使用 _ _import_ _ 函数获得特定函数
                  使用 _ _import_ _ 函数实现 延迟导入
                  使用 reload 函数
          关于名称空间
                  使用 dir 函数
                  使用 dir 函数查找类的所有成员
                  使用 vars 函数
          检查对象类型
                  使用 type 函数
                  对文件名和文件对象使用 type 函数
                  使用 callable 函数
                  使用 isinstance 函数
                  使用 issubclass 函数
          计算 Python 表达式
                  使用 eval 函数
                  使用 eval 函数执行任意命令
                  安全地使用 eval 函数求值
          编译和执行代码
                  使用 compile 函数检查语法
                  执行已编译的代码
                  简单的代码生成工具
                  使用 execfile 函数
                  hello.py 脚本
          从 _ _builtin_ _ 模块重载函数
                  显式地访问 _ _builtin_ _ 模块中的函数
  exceptions 模块
                  使用 exceptions 模块
  os 模块
          处理文件
                  使用 os 模块重命名和删除文件
          处理目录
                  使用 os 列出目录下的文件
                  使用 os 模块改变当前工作目录
                  使用 os 模块创建/删除多个目录级
                  使用 os 模块创建/删除目录
          处理文件属性
                  使用 os 模块获取文件属性
                  使用 os 模块修改文件的权限和时间戳
          处理进程
                  使用 os 执行操作系统命令
                  使用 os 模块启动新进程
                  使用 os 模块调用其他程序 (Unix)
                  使用 os 模块调用其他程序 (Windows)
                  使用 os 模块在后台执行程序 (Windows)
                  使用 spawn 或 fork/exec 调用其他程序
          处理守护进程(Daemon Processes)
                  使用 os 模块使脚本作为守护执行 (Unix)
                  使用 os 模块终止当前进程
  os.path 模块
          处理文件名
                  使用 os.path 模块处理文件名
                  使用 os.path 模块检查文件名的特征
                  使用 os.path 模块将用户名插入到文件名
                  使用 os.path 替换文件名中的环境变量
          搜索文件系统
                  使用 os.path 搜索文件系统
                  使用 os.listdir 搜索文件系统
                  使用 DirectoryWalker 搜索文件系统
                  使用 DirectoryStatWalker 搜索文件系统
  stat 模块
                  Using the stat Module
  string 模块
                  使用 string 模块
                  使用字符串方法替代 string 模块函数
                  使用 string 模块将字符串转为数字
  re 模块
                  使用 re 模块来匹配字符串
                  使用 re 模块抽出匹配的子字符串
                  使用 re 模块搜索子字符串
                  使用 re 模块替换子字符串
                  使用 re 模块替换字符串(通过回调函数)
                  使用 re 模块匹配多个模式中的一个
  math 模块
                  使用 math 模块
  cmath 模块
                  使用 cmath 模块
  operator 模块
                  使用 operator 模块
                  使用 operator 模块检查类型
  copy 模块
                  使用 copy 模块复制对象
                  使用 copy 模块复制集合(Collections)
  sys 模块
          处理命令行参数
                  使用sys模块获得脚本的参数
          处理模块
                  使用sys模块操作模块搜索路径
                  使用sys模块查找内建模块
                  使用sys模块查找已导入的模块
          处理引用记数
                  使用sys模块获得引用记数
                  使用sys模块获得当前平台
          跟踪程序
                  使用sys模块配置分析函数
                  使用sys模块配置单步跟踪函数
          处理标准输出/输入
                  使用sys重定向输出
          退出程序
                  使用sys模块退出程序
                  捕获sys.exit调用
                  另一种捕获sys.exit调用的方法
  atexit 模块
                  使用 atexit 模块
  time 模块
          获得当前时间
                  使用 time 模块获取当前时间
          将时间值转换为字符串
                  使用 time 模块格式化时间输出
          将字符串转换为时间对象
                  使用 time.strptime 函数解析时间
                  strptime 实现
          转换时间值
                  使用 time 模块将本地时间元组转换为时间值(整数)
                  将 UTC 时间元组转换为时间值(整数)
          Timing 相关
                  使用 time 模块评价算法
  types 模块
                  使用 types 模块
  gc 模块
                  使用 gc 模块收集循环引用垃圾
  更多标准模块
  概览
          文件与流
          类型封装
          随机数字
          加密算法
  fileinput 模块
                  使用 fileinput 模块循环一个文本文件
                  使用 fileinput 模块处理多个文本文件
                  使用 fileinput 模块将 CRLF 改为 LF
  shutil 模块
                  使用 shutil 复制文件
                  使用 shutil 模块复制/删除目录树
  tempfile 模块
                  使用 tempfile 模块创建临时文件
                  使用 tempfile 模块打开临时文件
  StringIO 模块
                  使用 StringIO 模块从内存文件读入内容
                  使用 StringIO 模块向内存文件写入内容
                  使用 StringIO 模块捕获输出
  cStringIO 模块
                  使用 cStringIO 模块
                  后退至 StringIO
  mmap 模块
                  使用 mmap 模块
                  对映射区域使用字符串方法和正则表达式
  UserDict 模块
                  使用 UserDict 模块
  UserList 模块
                  使用 UserList 模块
  UserString 模块
                  使用 UserString 模块
  traceback 模块
                  使用 traceback 模块打印跟踪返回信息
                  使用 traceback 模块将跟踪返回信息复制到字符串
                  使用 traceback Module 模块编码 Traceback 对象
  errno 模块
                  使用 errno 模块
                  使用 errorcode 字典
  getopt 模块
                  使用 getopt 模块
                  使用 getopt 模块处理长选项
  getpass 模块
                  使用 getpass 模块
  glob 模块
                  使用 glob 模块
  fnmatch 模块
                  使用 fnmatch 模块匹配文件
                  使用 fnmatch 模块将模式转换为正则表达式
  random 模块
                  使用 random 模块获得随机数字
                  使用 random 模块从序列取出随机项
                  使用 random 模块打乱一副牌
                  使用 random 模块生成高斯分布随机数
  whrandom 模块
                  使用 whrandom 模块
                  使用 whrandom 模块创建多个随机生成器
  md5 模块
                  使用 md5 模块
                  使用 md5 模块获得十六进制或 base64 编码的 md5 值
                  使用 md5 模块来处理口令的发送与应答的验证
                  使用 md5 模块检查数据完整性
  sha 模块
                  使用 sha 模块
  crypt 模块
                  使用 crypt 模块
                  使用 crypt 模块身份验证
  rotor 模块
                  使用 rotor 模块
  zlib 模块
                  使用 zlib 模块压缩字符串
                  使用 zlib 模块压缩多个不同类型文件
                  使用 zlib 模块解压缩流
                  压缩流的仿文件访问方式
  code 模块
                  使用 code 模块编译语句
                  使用 code 模块模拟交互解释器
                  使用 code 模块实现简单的 Debugging
  线程和进程
  概览
          线程
          进程
  threading 模块
                  使用 threading 模块
  Queue 模块
                  使用 Queue 模块
                  使用限制大小的 Queue 模块
                  使用 Queue 模块实现优先级队列
                  使用 Queue 模块实现一个堆栈
  thread 模块
                  使用 thread 模块
  commands 模块
                  使用 commands 模块
  pipes 模块
                  使用 pipes 模块
  popen2 模块
                  使用 popen2 模块对字符串排序Module to Sort Strings
                  使用 popen2 模块控制 gnuchess
  signal 模块
                  使用 signal 模块
  数据表示
  概览
          二进制数据
          自描述格式
          输出格式
          编码二进制数据
  array 模块
                  使用 array 模块将数列转换为字符串
                  作为普通序列操作阵列
                  使用阵列将字符串转换为整数列表
                  使用 array 模块判断平台字节序
                  使用 sys.byteorder 属性判断平台字节序( Python 2.0 及以后)
  struct 模块
                  使用 struct 模块
  xdrlib 模块
                  使用 xdrlib 模块
                  使用 xdrlib 模块发送 RPC 调用包
  marshal 模块
                  使用 marshal 模块组合不连续数据
                  使用 marshal 模块处理代码
  pickle 模块
                  使用 pickle 模块
                  使用 pickle 模块的二进制模式
  cPickle 模块
                  使用 cPickle 模块
  copy_reg 模块
                  使用 copy_reg 模块实现 code 对象的 pickle 操作
                  使用 copy_reg 模块实现文件对象的 pickle 操作
  pprint 模块
                  使用 pprint 模块
  repr 模块
                  使用 repr 模块
  base64 模块
                  使用 base64 模块编码文件
                  使用 base64 模块编码字符串
                  使用 base64 模块做基本验证
                  使用 base64 为 Tkinter 封装 GIF 格式
  binhex 模块
                  使用 binhex 模块
  quopri 模块
                  使用 quopri 模块
  uu 模块
                  使用 uu 模块编码二进制文件
                  使用 uu 模块解码 uu 格式的文件
  binascii 模块
                  使用 binascii 模块
  文件格式
  概览
          Markup 语言
          配置文件
          压缩档案格式
  xmllib 模块
                  使用 xmllib 模块获取元素的信息
                  使用 xmllib 模块
  xml.parsers.expat 模块
                  使用 xml.parsers.expat 模块
                  使用 xml.parsers.expat 模块读取 ISO Latin-1 文本
  sgmllib 模块
                  使用 sgmllib 模块提取 Title 元素
                  使用 sgmllib 模块格式化 SGML 文档
                  使用 sgmllib 模块检查格式
                  使用 sgmllib 模块过滤 SGML 文档
  htmllib 模块
                  使用 htmllib 模块
  htmlentitydefs 模块
                  使用 htmlentitydefs 模块
                  使用 htmlentitydefs 模块翻译实体
                  转义 ISO Latin-1 实体
  formatter 模块
                  使用 formatter 模块将 HTML 转换为事件流
                  使用 formatter 模块将 HTML 转换为纯文本
                  使用 formatter 模块自定义 Writer
  ConfigParser 模块
                  使用 ConfigParser 模块
                  使用 ConfigParser 模块写入配置数据
  netrc 模块
                  使用 netrc 模块
  shlex 模块
                  使用 shlex 模块
  zipfile 模块
          列出内容
                  使用 zipfile 模块列出 ZIP 文档中的文件
          从 ZIP 文件中读取数据
                  使用 zipfile 模块从 ZIP 文件中读取数据
          向 ZIP 文件写入数据
                  使用 zipfile 模块将文件储存在 ZIP 文件里
                  使用 zipfile 模块在 ZIP 文件中储存字符串
  gzip 模块
                  使用 gzip 模块读取压缩文件
                  给 gzip 模块添加 seek/tell 支持
  邮件和新闻消息处理
  概览
  rfc822 模块
                  使用 rfc822 模块
                  使用 rfc822 模块解析标头字段
  mimetools 模块
                  使用 mimetools 模块
  MimeWriter 模块
                  使用 MimeWriter 模块
                  MimeWriter 模块的辅助类
  mailbox 模块
                  使用 mailbox 模块
  mailcap 模块
                  使用 mailcap 模块获得 Capability 字典
                  使用 mailcap 模块获得打开
  mimetypes 模块
                  使用 mimetypes 模块
  packmail 模块
                  使用 packmail 打包单个文件
  mimify 模块
                  使用 mimify 模块解码信息
                  使用 mimify 模块编码信息
  multifile 模块
                  使用 multifile 模块
  chpt 7
  国际化
  locale 模块
                  使用 locale 模块获得当前平台 locale 设置
  unicodedata 模块
                  使用 unicodedata 模块
  ucnhash  模块
                  使用 ucnhash 模块
  多媒体相关模块
  概览
  imghdr 模块
                  使用 imghdr 模块
  sndhdr 模块
                  使用 sndhdr 模块
  whatsound 模块
                  使用 whatsound 模块
  aifc 模块
                  使用 aifc 模块
  sunau 模块
                  使用 sunau 模块
  sunaudio 模块
                  使用 sunaudio 模块
  wave 模块
                  使用 wave 模块
  audiodev 模块
                  使用 audiodev 模块
  winsound 模块
                  使用 winsound 模块
  数据储存
  概览
  anydbm 模块
                  使用 anydbm 模块
  whichdb 模块
                  使用 whichdb 模块
  shelve 模块
                  使用 shelve 模块
                  使用 shelve 模块处理给定数据库
  dbhash 模块
                  使用 dbhash 模块
  dbm 模块
                  使用 dbm 模块
  dumbdbm 模块
                  使用 dumbdbm 模块
  gdbm 模块
                  使用 gdbm 模块
  工具和实用程序
  dis 模块
                  使用 dis 模块
  pdb 模块
                  使用 pdb 模块
  bdb 模块
                  使用 bdb 模块
  profile 模块
                  U使用 profile 模块
  pstats 模块
                  使用 pstats 模块
  tabnanny 模块
                  使用 tabnanny 模块
  其他模块
  概览
  fcntl 模块
                  Using the fcntl Module
  pwd 模块
  grp 模块
  nis 模块
  curses 模块
  termios 模块
  tty 模块
  resource 模块
  syslog 模块
  msvcrt 模块
  nt 模块
  _winreg 模块
  posix 模块
  执行支持模块
  dospath 模块
  macpath 模块
  ntpath 模块
  posixpath 模块
  strop 模块
  imp 模块
  new 模块
  pre 模块
  sre 模块
  py_compile 模块
  compileall 模块
  ihooks 模块
  linecache 模块
  macurl2path 模块
  nturl2path 模块
  tokenize 模块
  keyword 模块
  parser 模块
  symbol 模块
  token 模块
  其他模块
  概览
  pyclbr 模块
                  使用 pyclbr 模块
                  使用 pyclbr 模块读取类和函数
                  使用 pyclbr 模块
  filecmp 模块
                  使用 filecmp 模块
  cmd 模块
                  使用 cmd 模块
  rexec 模块
                  使用 rexec 模块
  Bastion 模块
                  使用 Bastion 模块
                  使用 Bastion 模块处理非标准过滤器
  readline 模块
                  使用 readline 模块
  rlcompleter 模块
                  使用 rlcompleter 模块展开名字
  statvfs 模块
                  使用 statvfs 模块
  calendar 模块
                  使用 calendar 模块
                  使用 calendar 模块
  sched 模块
                  使用 sched 模块
  statcache 模块
                  使用 statcache 模块
  grep 模块
                  使用 grep 模块
  dircache 模块
                  使用 dircache 模块
  dircmp 模块
                  使用 dircmp 模块
  cmp 模块
                  使用 cmp 模块
  cmpcache 模块
                  使用 cmpcache 模块
  util 模块
                  实现 util 模块的 remove 函数
                  实现 util 模块的 readfile 函数
                  实现 util 模块的 readopenfile 函数
  soundex 模块
                  使用 soundex 模块
  timing 模块
                  使用 timing 模块
                  模拟 timing 模块
  posixfile 模块
                  使用 posixfile 模块
  bisect 模块
                  使用 bisect 模块向列表插入条目
                  使用 bisect 模块获得插入点位置
  knee 模块
                  使用 knee 模块
  tzparse 模块
                  使用 tzparse 模块
  regex 模块
                  使用 regex 模块
  regsub 模块
                  使用 regsub 模块
  reconvert 模块
                  使用 reconvert 模块
  regex_syntax 模块
                  使用 regex_syntax 模块
  find 模块
                  使用 find 模块
  Py 2.0 后新增模块


关于本书

五年前我偶然遇到了 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)

产品细节

本书使用DocBookSGML编写, 我使用了一系列的工具, 包括Secret Labs' PythonWorks, Excosoft Documentor, James Clark's Jade DSSSL processor, Norm Walsh's DocBookstylesheets, 当然,还有一些 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, 奇迹).

代码约定

本书使用以下习惯用法:

斜体

等宽字体 e.g. Python

等宽粗体

关于例子

除非提到,所有例子都可以在 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. 大家一定不要看~)

如何联系我们

Python 江湖 QQ 群: 43680167

Feather (校对) gt: andelf@gmail.com


核心模块


介绍

Python 的标准库包括了很多的模块, 从 Python 语言自身特定的类型和声明, 到一些只用于少数程序的不著名的模块.

本章描述了一些基本的标准库模块. 任何大型 Python 程序都有可能直接或间接地使用到这类模块的大部分.

内建函数和异常

下面的这两个模块比其他模块加在一起还要重要: 定义内建函数(例如 len, int, range ...)的 _ _builtin_ _模块, 以及定义所有内建异常的 exceptions模块.

Python 在启动时导入这两个模块, 使任何程序都能够使用它们.

操作系统接口模块

Python 有许多使用了 POSIX 标准 API 和标准 C 语言库的模块. 它们为底层操作系统提供了平台独立的接口.

这类的模块包括: 提供文件和进程处理功能的 os模块; 提供平台独立的文件名处理 (分拆目录名, 文件名, 后缀等)的 os.path模块; 以及时间日期处理相关的 time/datetime模块.

[!Feather注: datetime 为 Py2.3 新增模块, 提供增强的时间处理方法 ]

延伸一点说, 网络和线程模块同样也可以归为这一个类型. 不过 Python 并没有在所有的平台/版本实现这些.

类型支持模块

标准库里有许多用于支持内建类型操作的库. string模块实现了常用的字符串处理. math模块提供了数学计算操作和常量(pi, e都属于这类常量), cmath模块为复数提供了和 math一样的功能.

正则表达式

re模块为 Python 提供了正则表达式支持. 正则表达式是用于匹配字符串或特定子字符串的 有特定语法的字符串模式.

语言支持模块

sys 模块可以让你访问解释器相关参数,比如模块搜索路径,解释器版本号等. operator模块提供了和内建操作符作用相同的函数. copy模块允许 你复制对象, Python 2.0 新加入的 gc模块提供了对垃圾收集的相关控制功能.


_ _builtin_ _ 模块

这个模块包含 Python 中使用的内建函数. 一般不用手动导入这个模块; Python会帮你做好一切.

使用元组或字典中的参数调用函数

Python允许你实时地创建函数参数列表. 只要把所有的参数放入一个元组中, 然后通过内建的 apply函数调用函数. 如 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))

*B*whither canada?
1 5*b*

要想把关键字参数传递给一个函数, 你可以将一个字典作为 apply函数的第 3 个参数, 参考 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"})

*B*crunchy frog
crunchy frog
crunchy frog*b*

apply函数的一个常见用法是把构造函数参数从子类传递到基类, 尤其是构造函数需要接受很多参数的时候. 如 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)

*B*create a green <Rectangle instance at 8c8260> sized 100 x 100
create a blue <RoundedRectangle instance at 8c84c0> sized 10 x 20*b*

Python 2.0 提供了另个方法来做相同的事. 你只需要使用一个传统的函数调用 , 使用 *来标记元组, **来标记字典.

下面两个语句是等价的:

result = function(*args, **kwargs)
result = apply(function, args, kwargs)

加载和重载模块

如果你写过较庞大的 Python 程序, 那么你就应该知道 import语句是用来导入外部模块的 (当然也可以使用 from-import版本). 不过你可能不知道 import其实是靠调用内建 函数 _ _import_ _来工作的.

通过这个戏法你可以动态地调用函数. 当你只知道模块名称(字符串)的时候, 这将很方便. Example 1-4展示了这种用法, 动态地导入所有以 "-plugin" 结尾的模块.

使用 _ _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()

*B*example-plugin says hello*b*

注意这个 plug-in 模块文件名中有个 "-" (hyphens). 这意味着你不能使用普通的 import命令, 因为 Python 的辨识符不允许有 "-" .

Example 1-5展示了 Example 1-4中使用的 plug-in .

Plug-in 例子

File: example-plugin.py

def hello():
print "example-plugin says hello"

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

*B*<function open at 794fa0>*b*

你也可以使用这个函数实现延迟化的模块导入 (lazy module loading). 例如在 Example 1-7string模块只在第一次使用的时候导入.

使用 _ _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

*B*abcdefghijklmnopqrstuvwxyz*b*

Python 也提供了重新加载已加载模块的基本支持. [Example 1-8 #eg-1-8 会加载 3 次 hello.py文件.

使用 reload 函数

File: builtin-reload-example-1.py

import hello
reload(hello)
reload(hello)

*B*hello again, and welcome to the show
hello again, and welcome to the show
hello again, and welcome to the show*b*

reload 直接接受模块作为参数.

[!Feather 注:  ^ 原句无法理解, 稍后讨论.]

注意,当你重加载模块时, 它会被重新编译, 新的模块会代替模块字典里的老模块. 但是, 已经用原模块里的类建立的实例仍然使用的是老模块(不会被更新).

同样地, 使用 from-import直接创建的到模块内容的引用也是不会被更新的.

关于名称空间

dir返回由给定模块, 类, 实例, 或其他类型的所有成员组成的列表. 这可能在交互式 Python 解释器下很有用, 也可以用在其他地方. Example 1-9展示了 dir函数的用法.

使用 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

*B*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 => []
<built-in function len> => ['_ _doc_ _', '_ _name_ _', '_ _self_ _']
<module 'sys' (built-in)> => ['_ _doc_ _', '_ _name_ _',
'_ _stderr_ _', '_ _stdin_ _', '_ _stdout_ _', 'argv',
'builtin_module_names', 'copyright', 'dllhandle',
'exc_info', 'exc_type', 'exec_prefix', 'executable',
...*b*

在例子 Example 1-10中定义的 getmember函数返回给定类定义的所有类级别的属性和方法.

使用 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)

*B*['_ _doc_ _', '_ _module_ _', 'a', 'b']
['_ _doc_ _', '_ _module_ _', 'a', 'b', 'c', 'd']
['_ _doc_ _', '_ _getitem_ _', '_ _init_ _', '_ _module_ _', '_ _str_ _']*b*

getmembers函数返回了一个有序列表. 成员在列表中名称出现的越早, 它所处的类层次就越高. 如果无所谓顺序的话, 你可以使用字典代替列表.

[!Feather 注: 字典是无序的, 而列表和元组是有序的, 网上有关于有序字典的讨论]

vars函数与此相似, 它返回的是包含每个成员当前值的字典. 如果你使用不带参数的 vars, 它将返回当前局部名称空间的可见元素(同 locals()函数 ). 如 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()

*B*the library book contains more than 350 scripts*b*

检查对象类型

Python 是一种动态类型语言, 这意味着给一个定变量名可以在不同的场合绑定到不同的类型上. 在接下面例子中, 同样的函数分别被整数, 浮点数, 以及一个字符串调用:

def function(value):
print value
function(1)
function(1.0)
function("one")

type函数 (如 Example 1-12所示) 允许你检查一个变量的类型. 这个函数会返回一个 type descriptor (类型描述符), 它对于 Python 解释器提供的每个类型都是不同的.

使用 type 函数

File: builtin-type-example-1.py

def dump(value):
print type(value), value

dump(1)
dump(1.0)
dump("one")

*B*<type 'int'> 1
<type 'float'> 1.0
<type 'string'> one*b*

每个类型都有一个对应的类型对象, 所以你可以使用 is操作符 (对象身份?) 来 检查类型. (如 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"


*B*4672 bytes
4672 bytes*b*

callable函数, 如 Example 1-14所示, 可以检查一个对象是否是可调用的 (无论是直接调用或是通过 apply). 对于函数, 方法, lambda函式, 类, 以及实现了 _ _call_ _方法的类实例, 它都返回 True.

使用 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)

*B*0 is *not* callable
string is *not* callable
<built-in function callable> is callable
<function dump at 8ca320> is callable
A is callable
B is callable
<unbound method A.method> is callable
<A instance at 8caa10> is *not* callable
<B instance at 8cab00> is callable
<method A.method of B instance at 8cab00> is callable*b*

注意类对象 (A 和 B)都是可调用的; 如果调用它们, 就产生新的对象(类实例). 但是 A 类的实例不可调用, 因为它的类没有实现 _ _call_ _方法.

你可以在 operator模块中找到检查对象是否为某一内建类型(数字, 序列, 或者字典等) 的函数. 但是, 因为创建一个类很简单(比如实现基本序列方法的类), 所以对这些 类型使用显式的类型判断并不是好主意.

在处理类和实例的时候会复杂些. Python 不会把类作为本质上的类型对待; 相反地, 所有的类都属于一个特殊的类类型(special class type), 所有的类实例属于一个特殊的实例类型(special instance type).

这意味着你不能使用 type函数来测试一个实例是否属于一个给定的类; 所有的实例都是同样 的类型! 为了解决这个问题, 你可以使用 isinstance函数,它会检查一个对象是 不是给定类(或其子类)的实例. Example 1-15展示了 isinstance函数的使用.

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

*B*<A instance at 8ca6d0> => A
<B instance at 8ca750> => B
<C instance at 8ca780> => A C
<D instance at 8ca7b0> => A B D
0 =>
string =>*b*

issubclass函数与此相似, 它用于检查一个类对象是否与给定类相同, 或者是给定类的子类. 如 Example 1-16所示.

注意, isinstance可以接受任何对象作为参数, 而 issubclass函数在接受非类对象参 数时会引发 TypeError异常.

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

*B*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*b*

计算 Python 表达式

Python 提供了在程序中与解释器交互的多种方法. 例如 eval函数将一个字符串 作为 Python 表达式求值. 你可以传递一串文本, 简单的表达式, 或者使用 内建 Python 函数. 如 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')")

*B*1 => 1 <type 'int'>
1.0 => 1.0 <type 'float'>
'string' => string <type 'string'>
1.0 + 2.0 => 3.0 <type 'float'>
'*' * 10 => ********** <type 'string'>
len('world') => 5 <type 'int'>*b*

如果你不确定字符串来源的安全性, 那么你在使用 eval的时候会遇到些麻烦. 例如, 某个用户可能会使用 _ _import_ _函数加载 os模块, 然后从硬盘删除文件 (如 Example 1-18所示).

使用 eval 函数执行任意命令

File: builtin-eval-example-2.py

print eval("_ _import_ _('os').getcwd()")
print eval("_ _import_ _('os').remove('file')")

*B*/home/fredrik/librarybook
Traceback (innermost last):
File "builtin-eval-example-2", line 2, in ?
File "<string>", line 0, in ?
os.error: (2, 'No such file or directory')*b*

这里我们得到了一个 os.error异常, 这说明 Python 事实上在尝试删除文件!

幸运地是, 这个问题很容易解决. 你可以给 eval函数传递第 2 个参数, 一个定义了该表达式求值时名称空间的字典. 我们测试下, 给函数传递个空字典:

>>> print eval("_ _import_ _('os').remove('file')", {})
Traceback (innermost last):
File "<stdin>", line 1, in ?
File "<string>", 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 "<stdin>", line 1, in ?
File "<string>", line 0, in ?
os.error: (2, 'No such file or directory')
>>> namespace.keys()
['_ _builtins_ _']

如果你打印这个 namespace 的内容, 你会发现里边有所有的内建函数.

[!Feather 注: 如果我RP不错的话, 添加的这个_ _builtins_ _就是当前的_ _builtins_ _]

我们注意到了如果这个变量存在, Python 就不会去添加默认的, 那么我们的解决方法也来了, 为传递的字典参数加入一个 _ _builtins_ _项即可. 如 Example 1-19所示.

安全地使用 eval 函数求值

File: builtin-eval-example-3.py

print eval("_ _import_ _('os').getcwd()", {})
print eval("_ _import_ _('os').remove('file')", {"_ _builtins_ _": {}})

*B*/home/fredrik/librarybook
Traceback (innermost last):
File "builtin-eval-example-3.py", line 2, in ?
File "<string>", line 0, in ?
NameError: _ _import_ _*b*

即使这样, 你仍然无法避免针对 CPU 和内存资源的攻击. (比如, 形如 eval("'*'*1000000*2*2*2*2*2*2*2*2*2")的语句在执行后会使你的程序耗尽系统资源).

编译和执行代码

eval函数只针对简单的表达式. 如果要处理大块的代码, 你应该使用 compileexec函数 (如 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

执行已编译的代码

File: builtin-compile-example-2.py

BODY = """
print 'the ant, an introduction'
"""

code = compile(BODY, "<script>", "exec")

print code

exec code

*B*<code object ? at 8c6be0, file "<script>", line 0>
the ant, an introduction*b*

使用 Example 1-22中的类可以在程序执行时实时地生成代码. write方法用于添加代码, indentdedent方法用于控制缩进结构. 其他部分交给类来处理.

简单的代码生成工具

File: builtin-compile-example-3.py

import sys, string

class CodeGeneratorBackend:
"Simple code generator for Python"

def begin(self, tab="\t"):
self.code = []
self.tab = tab
self.level = 0

def end(self):
self.code.append("") # make sure there's a newline at the end
return compile(string.join(self.code, "\n"), "<code>", "exec")

def write(self, string):
self.code.append(self.tab * self.level + string)

def indent(self):
self.level = self.level + 1
# in 2.0 and later, this can be written as: self.level += 1

def dedent(self):
if self.level == 0:
raise SyntaxError, "internal error in code generator"
self.level = self.level - 1
# or: self.level -= 1

#
# try it out!

c = CodeGeneratorBackend()
c.begin()
c.write("for i in range(5):")
c.indent()
c.write("print 'code generation made easy!'")
c.dedent()
exec c.end()

*B*code generation made easy!
code generation made easy!
code generation made easy!
code generation made easy!
code generation made easy!*b*

Python 还提供了 execfile函数, 一个从文件加载代码, 编译代码, 执行代码的快捷方式. Example 1-23简单地展示了如何使用这个函数.

使用 execfile 函数

File: builtin-execfile-example-1.py

execfile("hello.py")

def EXECFILE(filename, locals=None, globals=None):
exec compile(open(filename).read(), filename, "exec") in locals, globals

EXECFILE("hello.py")

*B*hello again, and welcome to the show
hello again, and welcome to the show*b*

Example 1-24中的代码是 Example 1-23中使用的 hello.py 文件.

hello.py 脚本

File: hello.py

print "hello again, and welcome to the show"

从 _ _builtin_ _ 模块重载函数

因为 Python 在检查局部名称空间和模块名称空间前不会检查内建函数, 所以有时候你可能要显式地引用 _ _builtin_ _模块. 例如 Example 1-25重载了内建的 open函数. 这时候要想使用原来的 open函数, 就需要脚本显式地指明模块名称.

显式地访问 _ _builtin_ _ 模块中的函数

File: builtin-open-example-1.py

def open(filename, mode="rb"):
import _ _builtin_ _
file = _ _builtin_ _.open(filename, mode)
if file.read(5) not in("GIF87", "GIF89"):
raise IOError, "not a GIF file"
file.seek(0)
return file

fp = open("samples/sample.gif")
print len(fp.read()), "bytes"

fp = open("samples/sample.jpg")
print len(fp.read()), "bytes"

*B*3565 bytes
Traceback (innermost last):
File "builtin-open-example-1.py", line 12, in ?
File "builtin-open-example-1.py", line 5, in open
IOError: not a GIF file*b*

[!Feather 注: 明白这个open()函数是干什么的么? 检查一个文件是否是 GIF 文件, 
一般如这类的图片格式都在文件开头有默认的格式.
另外打开文件推荐使用file()而不是open() , 虽然暂时没有区别]

exceptions 模块

exceptions模块提供了标准异常的层次结构. Python 启动的时候会自动导入这个模块, 并且将它加入到 _ _builtin_ _模块中. 也就是说, 一般不需要手动导入这个模块.

在 1.5.2 版本时它是一个普通模块, 2.0 以及以后版本成为内建模块.

该模块定义了以下标准异常:

那么解释器将直接关闭而不会显示任何跟踪返回信息.

(经常会是一些深层次的东西, 比如 "eval_code2: NULL globals" )这本书的作者编了 5 年程序都没见过这个错误. (想必是没有用 raise SystemError).

你可以创建自己的异常类. 只需要继承内建的 Exception类(或者它的任意一个合适的子类)即可, 有需要时可以再重载它的 _ _str_ _方法. Example 1-26展示了如何使用 exceptions模块.

使用 exceptions 模块

File: exceptions-example-1.py

# python imports this module by itself, so the following
# line isn't really needed
# python 会自动导入该模块, 所以以下这行是不必要的
# import exceptions

class HTTPError(Exception):
# indicates an HTTP protocol error
def _ _init_ _(self, url, errcode, errmsg):
self.url = url
self.errcode = errcode
self.errmsg = errmsg
def _ _str_ _(self):
return (
"<HTTPError for %s: %s %s>" %
(self.url, self.errcode, self.errmsg)
)

try:
raise HTTPError("http://www.python.org/foo", 200, "Not Found")
except HTTPError, error:
print "url", "=>", error.url
print "errcode", "=>", error.errcode
print "errmsg", "=>", error.errmsg
raise # reraise exception

*B*url => http://www.python.org/foo
errcode => 200
errmsg => Not Found
Traceback (innermost last):
File "exceptions-example-1", line 16, in ?
HTTPError: <HTTPError for http://www.python.org/foo: 200 Not Found>*b*

os 模块

这个模块中的大部分函数通过对应平台相关模块实现, 比如 posixnt. os模块会在第一次导入的时候自动加载合适的执行模块.

处理文件

内建的 open / file函数用于创建, 打开和编辑文件, 如 Example 1-27所示. 而 os模块提供了重命名和删除文件所需的函数.

使用 os 模块重命名和删除文件

File: os-example-3.py

import os
import string

def replace(file, search_for, replace_with):
# replace strings in a text file

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

try:
# remove old temp file, if any
os.remove(temp)
except os.error:
pass

fi = open(file)
fo = open(temp, "w")

for s in fi.readlines():
fo.write(string.replace(s, search_for, replace_with))

fi.close()
fo.close()

try:
# remove old backup file, if any
os.remove(back)
except os.error:
pass

# rename original to backup...
os.rename(file, back)

# ...and temporary to original
os.rename(temp, file)

#
# try it out!

file = "samples/sample.txt"

replace(file, "hello", "tjena")
replace(file, "tjena", "hello")

处理目录

os模块也包含了一些用于目录处理的函数.

listdir函数返回给定目录中所有文件名(包括目录名)组成的列表, 如 Example 1-28所示. 而 Unix 和 Windows 中使用的当前目录和父目录标记(. 和 .. )不包含在此列表中.

使用 os 列出目录下的文件

File: os-example-5.py

import os

for file in os.listdir("samples"):
print file

*B*sample.au
sample.jpg
sample.wav
...*b*

getcwdchdir函数分别用于获得和改变当前工作目录. 如 Example 1-29所示.

使用 os 模块改变当前工作目录

File: os-example-4.py

import os

# where are we?
cwd = os.getcwd()
print "1", cwd

# go down
os.chdir("samples")
print "2", os.getcwd()

# go back up
os.chdir(os.pardir)
print "3", os.getcwd()

*B*1 /ematter/librarybook
2 /ematter/librarybook/samples
3 /ematter/librarybook*b*

makedirsremovedirs函数用于创建或删除目录层,如 Example 1-30所示.

使用 os 模块创建/删除多个目录级

File: os-example-6.py

import os

os.makedirs("test/multiple/levels")

fp = open("test/multiple/levels/file", "w")
fp.write("inspector praline")
fp.close()

# remove the file
<