学习Python

目录:

概述

注解

学习 Python 不要将时间浪费在记 API 的功能上,而应该学习 Python 的编程理念。

对于重要模块 os, sys,应该尽量熟悉模块里的方法和属性; 对于常用的 API,应该熟悉使用方法;记不住也没关系,重要的是要学会使用 Python Manuals

os 和 sys 模块

sys 模块与 Python 解析器相关:

  1. sys.path

列举了 Python 解析器真正的搜索路径。 当模块被载入时,Python 从左到右依次获取 sys.path 中的目录。 每获取一个目录,就遍历目录中的文件,直至找到和模块名相同的文件名为止。

sys.path 在 Python 解析器运行的时候初始化。 Python 加载环境变量 PYTHONPATH 的值,作为 sys.path 的初始值。 当然 sys.path 的值不都是来自于 PYTHONPATH,它的值是可以修改的。

警告

sys.path 的修改维持到 Python 解析器退出

访问 sys.path 可以使用 os.getcwd() 函数。

  1. sys.modules
列举已经加载的模块。 这是一个字典结构
  1. sys.exec_info()
发生异常时,可以通过这个接口获取异常类型,值以及回溯对象。
  1. 标准输入输出流

标准流包括:

  • sys.stdin
  • sys.stdout
  • sys.stderr
  1. sys.argv

    获取命令行参数

os 模块与 Python 解析器运行的操作系统有关:

环境变量 os.environ
运行程序工具 os.system
创建进程 os.fork
描述文件和锁 os.open
文件处理 os.remove, os.rename
管理工具 os.getcwd
跨平台工具 os.path os.sep
路径名工具 os.path

脚本中运行命令行

os 模块提供了工具,可以在 Python 脚本中执行命令行。

函数名 功能
os.system 在 Python 脚本中执行命令行
os.popen 执行命令行并连接输入输出流

另外, 模块 subprocess 对命令行中流的控制比上面两个函数更全面。

与命令行的“通信”

os.system() 只是简单地运行命令行;os.popen() 连接命令的标准输入或者输出流。 默认情况下,获取一个类文件对象,连接命令行的输出(如果用 'w' 标志,则是命令行的输入)。 通过该对象,可以读取命令行产生的输出。

1
2
os.popen('type 1.txt').read()
os.popen('type 2.txt').readlines()

程序使用方式

每个 Python 模块都有一个属性变量 __name__。 当 Python 将模块当做程序运行时,模块的 __name__ 的值为 __main__; 当模块作为库文件加载时,__name__ 的值不再是 __main__

内部 APIs(常用的)

名称 功能
dir 列举类的所有属性和成员

(over)

脚本上下文

“Python scripts do not run in a vacuum.”

Python 不是运行在真空中。

当前工作目录

CWD——Current Working Directory

当前工作目录是一个十分重要的概念,是脚本处理的文件默认“呆”的地方,除非脚本中的文件名是绝对路径。 前一章提到,os.getcwd() 获取 CWD 的名称,os.chdir() 允许脚本将 CWD 转移到新的路径。

记住,不带完整路径的文件名会自动映射到 CWD 中,和 PYTHONPATH 没有关系。 从技术实现上看,脚本总是从 CWD 中启动的,而不是脚本所在的目录。 与此相反的是,import 脚本总是包含脚本的目录开始,不是 CWD (除非脚本恰好也处在 CWD 下)。

在命令行窗口运行 Python 脚本:

_images/cwd_test.png

CWD 的值是 C:。 打印系统搜索路径的前6项(os.path[0:6])会发现 D: 也在其中。 这说明 Python 会自动将脚本的根目录添加到系统搜索路径中。 这样的话,无论在哪运行脚本,该脚本都可以直接加载相同目录下的其它文件。

假定 test.pyD: 目录下,则可以直接加载:

import test

希尔环境变量

  • os.environ 存储所有环境变量

  • 获取环境变量

    os.environ 是一个 Python 的字典,因而可以通过键名访问对应的键值。

    例如,设置系统环境变量 PYTHONPATH 之后,运行 Python 解析器,就会将 PYTHONPATH 自动加载到 os.environ 中。 可以通过 os.environ["PYTHONPATH"] 语句来访问。

  • 修改环境变量

    由于 os.environ 是一个字典,因而可以通过赋值的方式来修改环境变量。

    注意

    父进程修改的环境变量可以被子进程继承。 反之,子进程修改的环境变量对于父进程是不可见的。

    典型的例子:在命令窗口中执行脚本,命令窗口程序是父进程,通过 set 修改的环境变量可以被脚本程序继承。 而脚本程序中的环境变量的修改不会在命令窗口中体现出来。

    Python 产生子进程的方法有:

    • os.popen
    • subprocess.popen
    • os.system
    • os.fork
    • os.spawnv
    • os.fork, etc.

标准流

1
2
3
sys.stdout.write('hello,world\n') # print('hello,world')
sys.stdin.readline() # in = input()
                     # print in
  • 标准输入流的数据默认来自于键盘输入
  • 标准输出流默认将输出文本打印到控制台窗口
  • 标准错误流默认将错误信息打印到控制台窗口

流重定向

为什么要引入流重定向呢? 最直接的应用是 Python 脚本进行白盒测试:提供输入,测试输出信息。 要截获输出到控制台的文本信息,必须用到流重定向。

在 Windows 命令窗口中这种重定向比较简单,使用 >/>> 命令可以很方便地将文本信息输出到某个文件中。例如:

1
2
3
echo hello,world > 1.txt      ; 从 1.txt 开头进行覆盖
echo hello,world >> 1.txt     ; 从 1.txt 结尾追加
python input_name.py < 1.txt  ; 将 1.txt 的内容给脚本 input_name.py 的标准输入流

如果想将输出信息传递给另一个命令行,或者程序,可以使用管道指令 |

1
2
3
4
# 1.py

import sys
print sys.argv[1]

在命令窗口中执行指令:echo hello,world | python 1.py,打印结果为 hello,world

流重定向到 Python对象

前面的流重定向都依赖于命令行,本节将介绍将流直接重定向到 Python 文件对象的方法。

Python 有一个很有意思的思想:

“If it looks like a duck and quacks like a duck, it must be a duck.”

长得像鸭子,叫得像鸭子,肯定是鸭子。

提供文件方法的对象都可以作为标准流:

  • read() 方法的对象可以赋值给 sys.stdin; read() 为输入流提供数据
  • write() 方法的对象可以赋值给 sys.stdout; 所有标准输出都发给 write() 方法。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Input(object):
    def read(self):
        return 'hello, world\n'
class Output(object):
    def write(self, s):
        f = open('1.txt', 'w')
        f.write(s)
        f.close()

sys.stdin = Input()
sys.stdin.read() # 'hello, world'
sys.stderr = Input()
sys.stderr.read() # 'hello, world'
sys.stdout = Output()
sys.stdout.write('hello, world\n') #生成文件 1.txt,输入文本 'hello, world\n'

print() 的重定向

Python模块

目录:

subprocess模块

subprocess.Popen

注解

构造函数常用参数:

  • args 字符串或者参数序列。
  • shell=False 是否打开命令窗口执行命令行
  • stdin=None 可以取 PIPE,文件句柄,文件描述符和 None
  • stdout=None 可以取 PIPE,文件句柄,文件描述符和 None
  • stderr=None 可以取 PIPE,文件句柄,文件描述符, STDOUTNone

重要

流对象为 None 时,子进程将继承父进程的标准流。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#D:\hello_world.py
print hello,world

#D:\test_subprocess.py
from subprocess import *

# ``shell = True`` cannot be skipped, as it uses shell to run the command line
open_obj = Popen('hello_world.py', shell = True, stdout = PIPE)
# If you want to ignore ``shell`` parameter, you can use executable parameter as below:
# open_obj = Popen('python hello_world.py', stdout = PIPE)

out_obj = open_obj.communicate()
print open_obj[0]

Popen 实例

  • poll() 子进程是否结束,返回 returncode 属性值

  • wait() 等待子进程结束,返回 returncode 属性值

    警告

    构造 Popen 对象时,不要使用 PIPE 参数,会死锁。

  • communicate() 阻塞式执行命令行,返回元组 (stdoudata, stderrdata)

    注解

    要返回元组 (stdoudata, stderrdata),实例化时,必须设置 stdout=PIPE; 要想将数据传递给子进程的输入流,必须设置 stdin=PIPE

  • send_signal() 发信号给子进程(SIGTERM)

  • terminate() 终止子进程

  • kill() 杀死子进程

注解

Windows 中 kill()/terminate() 一样,都是调用 Windows API:TerminateProcess; Unix 中 terminate() 发送消息 SIGTERMkill() 发送消息 SIGKILL

  • pid 表示子进程的 ID;如果使用 shell=True,则表示命令窗进程的 ID
  • returncode None 表示子进程未结束;Unix 中,-N 表示等待信号 N 结束子进程。
  • stdout 如果实例化时,设置 stdout=PIPE,则 stdout 为子进程的输出流;否则为 None
  • stderr 如果实例化时,设置 stderr=PIPE,则 stderr 为子进程的错误流;否则为 None
  • stdin 如果实例化时,设置 stdin=PIPE,则 stdin 为子进程的输入流;否则为 None
1
2
open_obj = Popen('python hello_world.py', stdout=PIPE)
print open_obj.stdout.read()

subprocess 的便捷接口

  • call() 阻塞式执行命令行,返回 returncode 属性值

    警告

    不能设置参数 stdout=PIPE/stderr=PIPE,会死锁

  • check_call() 阻塞式执行命令行,返回0,表示子进程正常退出; 否则抛出异常 CalledProcessError

  • check_output() 阻塞式执行命令行,正常情况下返回命令行输出(字节数组); 否则抛出异常 CalledProcessError

    注解

    不能使用 stdout=PIPE,可以使用 stderr=STDOUT 来捕获并输出错误信息。

URL访问的扩展库—— urllib2

urllib2 主要用于基础和摘要式的身份验证,网页跳转,网页 cookie 等等。

  • urllib2.urlopen(url, [,data][,timeout])

    • url

      字符串 / Request 对象。

      警告

      HTTPS 请求不进行服务器认证

    • data

      取值为字符串或者 None,定义传递给服务器的用户数据。

      重要

      目前为止,HTTP 请求是唯一用到 data 参数的用户请求;

      data 不为 None 时,HTTP 请求为 POST 方式。 data 必须符合 application/x-www-form-urlencoded 格式规范。 例如:name='hwz'&region='beijing'

      可以调用函数 urllib.urlencode() 做数据格式转换:

      1
      2
      3
      4
      5
      import urllib
      
      dic = {"name":"hwz", "region":"beijing"}
      encoded_data = urllib.urlencode(dic)
      print encoded_data # 'region=beijing&name=hwz'
      

      urllib.urlencode() 的输入参数为字典或者二元组序列,返回的是 application/x-www-form-urlencoded 格式的字符串。 urllib2 模块支持 HTTP/1.1 版本的请求,请求头中带有 Connection:close 键值。

    • timeout

      指定连接超时时间(s),等待连接是阻塞式的; 若没有指定,使用的是全局默认的数值。

      重要

      该参数仅对 HTTP, HTTPS 和 FTP 连接起作用。

    • 返回值

      返回一个仿文件对象,指向的是服务器的响应消息。

      注解

      服务器的 HTTP 响应消息,包括响应头(元信息)和响应体(也就是数据资源)。 响应体可以是 text/html 文档,也就是浏览器中的网页的源代码; 也可以是图片资源,还可以是二进制的数据,或者 application/json 字符串等等。

      返回对象除了常规文件读写方法之外,还提供两个额外的方法:

      • geturl()

        获取服务器返回的资源对应的 URL;URL 指含有该资源的网址; 比如网页资源,则返回该网页的 URL:

        1
        2
        response = urllib2.open('http://www.baidu.com')
        print response.geturl() # 'http://www.baidu.com'
        
      • info()

        返回服务器响应的元信息,比如响应头信息。 其格式是 mimetools.Message

        可以通过键名获取响应头信息,比如:

        1
        2
        3
        response = urllib2.open('http://www.baidu.com')
        meta_data = response.info()
        print meta_data.getheaders('Content-Type') # ['text/html; charset=utg-8']
        
    • 异常

      URLError

  • urllib2.install_opener(opener)

    手动安装全局访问器。

    重要

    系统默认安装的全局访问器,使用 UnknownHandler 请求处理器; 如果设置了 *_proxy 环境变量(例如 set http_proxy=*),全局访问器使用的 ProxyHandler

    <OpenerDirector instance>.open() 代替 urlopen(),可以不用安装全局访问器。

  • urllib2.build_opener([handler,...])

    返回一个访问器对象。

    访问器内部设置了请求处理器列表,可以通过 handler,... 手动设置处理列表。

    handler,...BaseHandler 的实例/不带参数的子类。

    以下请求处理器将自动排在 handler,... 前面(出现在 handler,... 中的除外):

    • ProxyHandler
    • UnknownHandler
    • HttpHandler
    • HttpDefaultErrorHandler
    • HttpRedircetHandler
    • FTPHandler
    • FileHandler
    • HTTPErrorProcessor

    如果安装 Python 的时候支持 SSL(即可以加载 ssl 模块),还会加入 HTTPSHandler

  • urllib2.Request(url, [data][,headers][,origin_req_host][,unverifiable])

    注解

    请求类

    • url

      URL 字符串。

    • data

      urllib2.urlopen()data 参数说明一致

    • headers

      headers 是一个字典。

      对于 headers 的处理,相当于调用 add_header(); 表示给请求头添加新的键值对,比如指定 User-Agent 键值对。

      注解

      服务器可以利用 User-Agent 字段过滤请求。 例如,Mozilla 火狐浏览器的 User-AgentMozilla/5.0 (X11; U; Linux i686) Gecko/20071127 FireFox/2.0.0.11; 而 urllib2User-Agent 默认为 Python-urllib/*.*。 如果某个服务器只接受 User-AgentMozilla/5.0 (X11; U; Linux i686) Gecko/20071127 FireFox/2.0.0.11 的请求, 则使用 urllib2 的脚本发起的网络请求会被过滤掉。

      这样做的好处是可以让服务器只接受来自浏览器的请求,而不是脚本发起的请求。 当然这种限制也不是绝对的,可以手动修改 User-Agent 键值达到目的。 因此,Python 文档用了 spoof 这个词(“糊弄” User-Agent)。

    最后两个参数和三方的 HTTP cookies 解析有关:

    • origin_req_host

      默认为 cookielib.request_host(self),表示请求指定的服务器主机名或者 IP 地址。 例如,如果请求的是 HTML 文档,则该参数是目标网页的主机名:

      1
      2
      3
      import urllib2, cookielib
      request = urllib2.Request('http://www.baidu.com')
      host_name = cookielib.request_host(request) # 'www.baidu.com'
      
    • unverifiable 表示请求是否可验证(RFC 2965),默认为 False。 对于一个不可验证的请求对应的 URL,用户是无权决定是否访问的。 例如,请求 HTML 文档中的图片,用户无权决定是否自动获取该图片,则这个参数设为 True

      注意

      许多网页就是这样,不受用户控制,自动弹出。

Request 实例

包含以下公有方法:

  • add_data(data)

  • get_method() "POST"/"GET"/...,仅对 HTTP 请求有意义。

  • has_data()

  • get_data()

  • add_header(key,val)

    给请求头添加新的键值对,只有 HTTP 处理器会受理这些键值对。

    注解

    键名不能相同,如果相同,则后一次的键值会覆盖前一次的键值。

  • add_unredirected_header(key,header) 添加一个键值对;如果需要做重定向,该键值对不会加入到重定向请求头中

  • has_header(header) 请求头中是否含有指定键值对

  • get_full_url() 返回构造函数提供的 URL

  • get_type() 返回协议类型

  • get_host() 返回主机名

  • get_selector() 获取 URL 选择子

  • set_proxy(host, type) 设置一个代理服务器,表示将生成一个代理请求实例。

    注解

    host 覆盖 get_host() 的返回值; type 覆盖 get_type() 的返回值; 选择子是 get_full_url() 的返回值。

  • get_origin_req_host() 返回原始主机名(RFC 2965)。

  • is_unverifiable() 请求是否可验证。

OpenerDirector 实例

  • add_handler(handler)

    增加一个处理器。

    处理器将添加以下操作序列:

    • protocol_open() 打开协议 URLs;
    • http_error_type() 处理 HTTP 错误对应的错误类型;
    • protocol_error() 处理协议错误(HTTP 处理器会忽略该函数);
    • protocol_request() 预处理协议请求;
    • protocol_response() 后处理协议响应;
  • open(url[,data][,timeout])

    注解

    urlopen() 一样,不同的是,本函数使用局部访问器

  • error(proto[,arg[,...]])

    proto 指定协议类型;

    用协议指定的错误处理器处理当前协议错误。 返回一个收集错误信息的仿文件对象。

    注解

    HTTP 协议使用响应状态码指定错误处理器。

OpenerDirector 实例打开 URL 的几个阶段:

  1. 调用所有处理器的 protocol_request,预处理请求。

  2. 调用所有处理器的 protocol_open,解析请求。

    如果某个处理器返回非 None 值(即服务器响应),或者抛出异常(通常为 URLError),这个阶段结束。 发生的异常允许继续传递。

    事实上,以上算法先尝试 default_open(); 如果都返回 None,再尝试 protocol_open(); 如果返回 None,则再尝试 unknown_open()

  3. 处理器调用 protocol_response,用于后处理响应。

BaseHandler 实例

BaseHandler 实例提供两个基础方法,可以直接调用:

  • add_parent(director) 添加一个访问器
  • close() 删除所有访问器

重要

以下属性和方法只能在派生类中实现或使用:

  • parent 指定的 OpenerDirector 实例

  • default_open(req)

    派生类如果想获取所有的 URL,必须实现这个方法。

    派生类如果实现了这个方法,则会被 add_parent() 指定的访问器对象调用。 它返回一个仿文件对象(如果没有访问器,则返回 None)。

    抛出异常 URLError

    重要

    该方法在所有打开方法(*_open())之前调用

  • protocol_open(req)

    注解

    该方法的名称依据协议来定; 之后凡是 protocol_ 开头的方法都是跟随协议名称的,不再复述。

    比如: HTTP 协议的打开方法为 http_open(); ftp 协议的打开方法为 ftp_open() 等。

    派生类如果想用指定的协议解析 URL,必须实现这个方法。

    派生类如果实现了这个方法,则会被 add_parent() 指定的访问器对象调用。 它返回一个仿文件对象(如果没有访问器,则返回 None)。

  • unknown_open(req)

    派生类如果想不用任何处理器获取所有的 URL,必须实现这个方法。

    参数说明和返回值以及异常类型和 protocol_open() 一样。

  • http_error_default(req, fp, code, msg, hdrs)

    派生类如果想捕获所有 HTTP 错误码,必须实现这个方法。

    派生类如果实现了这个方法,则会被 add_parent() 指定的访问器对象调用。

    警告

    用户不能调用这个方法

    • req Request 实例
    • fp 仿文件对象,指向 HTTP 错误消息体
    • code 三个数字表示的错误码
    • msg 用户可见的错误码的解释文字
    • hdrs 一个字典对象,表示错误头的键值对

    返回值与异常类型和 urlopen() 相同。

  • http_error_nnn(req, fp, code, msg, hdrs)

    派生类如果想捕获 HTTP 错误码 nnn,必须实现这个方法。

    派生类如果实现了这个方法,发生错误码 nnn 时,add_parent() 指定的访问器对象会自动调用对应的 http_error_nnn() 方法。

    参数说明和返回值以及异常类型和 http_error_default() 一样。

  • protocol_request(req)

    如果派生类想要预处理指定协议的请求实例,必须实现这个方法。

    派生类如果实现了这个方法,则会被 add_parent() 指定的访问器对象调用。

    req 是预处理前的 Request 实例,返回的是预处理后的 Request 实例。

  • protocol_response(req, response)

    派生类如果想后处理指定协议的服务器响应,必须实现这个方法。

    派生类如果实现了这个方法,则会被 add_parent() 指定的访问器对象调用。

    • req 是一个 Request 实例
    • response 有和 urlopen() 返回的对象一样的方法。

HTTPRedircetHandler 实例

  • redirect_request(req, fp, code, msg, hdrs, newurl)

    返回一个 Request 实例或者 None

    如果服务器返回一个重定向的响应(即错误响应消息 301 302 等等), 则在方法 http_error_30*() 中自动调用 redirect_request() 方法。 然后用生成的请求实例发出新的网络请求,以重定向到新的 URL。 如果没有处理器可以解析新的 URL,则抛出 HTTPError 异常; 如果 HTTPRedircetHandler 不能解析新的 URL,但存在其他处理器可以解析,则返回 None

  • http_error_301(req, fq, code, msg, hdrs)

    当服务器返回 moved permanently 消息时,add_parent() 指定的访问器会调用 http_error_301()

  • http_error_302(req, fp, code, msg, hdrs)

    当服务器返回 found 消息时,add_parent() 指定的访问器会调用 http_error_301()

  • http_error_303(req, fp,code, msg, hdrs)

    当服务器返回 see other 消息时,add_parent() 指定的访问器会调用 http_error_301()

  • http_error_307(req, fp, code, msg, hdrs)

    当服务器返回 temporary redirect 消息时,add_parent() 指定的访问器会调用 http_error_301()

BaseHTTPServer

注解

本模块针对的是 HTTP 协议。

BaseHTTPServer 模块定义了两个类,用于构造 HTTP 服务器。 通常这两个类不直接拿来使用,而作为基类进行派生。

  • BaseHTTPServer.HTTPServer(server_address, RequestHandlerClass)

    SocketServer.TCPServer 的子类,实现了 SocketServer.BaseServer 的接口。

    HTTPServer 创建和监听 HTTP socket,分发请求给处理器。

    创建和运行服务器的代码示例:

    1
    2
    3
    4
    def run(server_class=BaseHTTPServer.HTTPServer, handler_class=BaseHTTPServer.BaseHTTPRequestHandler):
        server_address = ('', 3000)
        httpd = server_class(server_address, handler_class)
        httpd.serve_forever()
    

    构造函数参数说明:

    • server_address 二元组 (server_name, server-port); 如果 server_name 是 ‘’,表示服务器为本主机。
    • RequestHandlerClass 请求处理器类名,可以传递 BaseHTTPServer.BaseHTTPRequestHandler
  • BaseHTTPServer.BaseHTTPRequestHandler

    定义处理器对象,用于解析服务器接收的 HTTP 请求。 它的实例不参与解析 HTTP 请求,一般是通过它的子类实例来完成。

    处理器解析请求和头信息之后,调用与请求类型对应的方法。 例如:请求类型为 SPAM,则对应的方法为 do_SPAM()。 该方法不带任何参数。

    重要

    BaseHTTPServer.BaseHTTPRequestHandler 的子类不需要修改 __init__() 方法。

BaseHTTPRequestHandler 的实例变量

  • client_address 是一个二元组 (host, port),表示客户端主机地址

  • server BaseHTTPServer 实例

  • command 请求类型,如 GET

  • path 请求路径

    例如:客户端请求 URL 为: http://127.0.0.1:2000/search?name=huwz&pwd=123456,则 path 为 /search?name=huwz&pwd=123456

  • request_version 请求的协议版本,例如:HTTP/1.0

  • headers

    类变量 MessageClass<message_class>` 的值是一个类对象。 headers 就是这个类对象的实例,用于解析和管理 HTTP 请求头。

  • rfile 输入流,指向用户请求中附带数据的起始位置

  • wfile 输出流,指向服务器响应数据的起始位置,返回给客户端

BaseHTTPRequestHandler 的类变量

  • server_version

    表示服务器软件版本,可以修改它的值; server_version 由多个字符串构成,字符串之间以空格隔开。 每个字符串的格式:<name>[/<version>],例如:BaseHTTP/0.2

  • sys_version

    表示 Python 系统版本,采取 server_version 或者 version_string() 支持的格式。如 Python/1.4

  • error_message_format

    指定一个格式化字符串,用于构建错误响应消息,发送给客户端。

    其中:

    code 是整数,表示 HTTP 错误码;message 为错误简略信息,explain 为错误详细解释。

    默认的 messageexplain 可以从类变量 responses 中获取。

  • error_content_type

    指定服务器错误响应头的 Content-Type 值。 默认值为 text/html

  • protocol_version

    定义服务器响应的 HTTP 协议版本。 如果设为 HTTP/1.1,则服务器允许 HTTP 长连接; 服务器所有响应的 HTTP 头必须设置准确的 Content-Lengthsend_header())。 出于后向兼容的考虑,默认版本为 HTTP/1.0

  • MessageClass

    表示仿 rfc822.Message 类,用于解析 HTTP 头。 默认值为 mimetools.Message,子类一般不会修改它。

  • resposnes

    {code:(shormessage, longmessage)}

    它是一个字典,表示错误码到 (短信息, 长信息) 的映射(符合 error_message_format 指定的格式)。

BaseHTTPRequestHandler 的方法

  • handle()

    处理接收的 HTTP 请求,会调用一次 handle_one_request() ,启动长连接之后,会调用多次。 子类不用修改它;只要实现合适的 do_*() 方法即可。

  • handle_one_request()

    解析和分发请求到合适的 do_*() 方法中。 子类不用修改它。

  • send_error(code[,message])

    发送错误码和错误信息给客户端。 code 表示 HTTP 错误码; message 是可选的。

    发完头信息之后,发送错误信息文本(由 error_message_format 构建)。

  • send_response(code[,message])

    发送一个响应头(类似于 HTTP/1.1 200 OK),打印与接收请求相关的日志; 之后发送服务器头(version_string())和数据头(data_time_string())。

  • send_header(keyword, value)

    给输出流的 HTTP 头增加一个键值对。

  • end_headers()

    给输出流的 HTTP 头增加一个空白行,表示结束

  • log_request([code][,size])

    成功接收请求时,打印日志到标准输出流。

    code 为 HTTP 响应状态码; size 表示响应消息体的长度。

  • log_error(...)

    不能完成请求时,打印错误日志。 默认情况下,将信息传递给 log_message()

  • log_message(format, ...)

    将任意信息发送给 sys.stderr

    每个打印消息都会在前面加上客户端的 ip 地址,当前日期和时间。

  • version_string()

    返回服务器软件版本字符串; 由 server_versionsys_version 组合而成。

  • date_time_string([timestamp])

    返回指定时间戳(time.time())的日期和时间;用于消息头。

    如果参数 timestamp 省略,则使用当前日期和时间。

    其格式类似于:Sun, 08 Feb 2015 23:09:30 GMT

  • log_date_time_string()

    返回当前日期和时间,用于日志打印。

  • address_string()

    返回客户端的地址,用于日志打印。 主机名称通过客户端 IP 地址查找。

注解

log_message() 内部调用 log_data_time_string()address_string() 方法

unittest

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import unittest

class TestAdd(unittest.TestCase):
    def setUp(self):
        print 'hello'
    def tearDown(self):
        print 'world'
    def test_add(self):
        self.assertEqual(3, 12)
    def test_sub(self):
        self.assertEqual(4, 4)

if __name__ == '__main__':
    unittest.main()

在执行每个测试案例之前,都是执行 setUp(); 案例运行结束之后,都会执行 tearDown()。 以上的案例会运行两次 setUp() 和两次 tearDown()

可以定义类函数 setupClass()tearDownClass()

1
2
3
4
5
6
7
@classmethod
def setupClass(cls):
    <code here>

@classmethod
def tearDownClass(cls):
    <code here>

所有测试案例执行之前执行一次 setupClass(); 所有测试案例执行之后执行一次 tearDownClass()

注解

测试类中以 test_ 开始的类方法都是一个测试案例。