Python库非常多,为方便快速查询,将自己之前用到的库做个简单汇总记录,不定期持续更新。
shutil
shutil模块提供目录和文件的高级操作
- 复制操作 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- import shutil 
 #将文件src复制到文件或目录dest,保留文件权限
 shutil.copy(src, dest)
 #在shutil.copy的基础上加上copystat(),即将文件的访问/修改时间等信息也复制
 shutil.copy2(src, dest)
 #复制文件src的内容(不包含元数据)到文件dest(不支持目录复制,dest中必须包含文件名)
 shutil.copyfile(src, dest)
 #将类文件对象src.log的内容复制到类文件对象dest.log
 shutil.copyfileobj(open('src.log','r'), open('dest.log', 'w'))
 #递归拷贝src。symlinks=True则软链接文件也会被复制
 shutil.copytree(src, dest, symlinks=True, ignore=shutil.ignore_patterns('*.pyc', '*.swap'))
- 移动&删除操作 - 1 
 2
 3
 4
 5- #递归方式移动文件或目录 
 shutil.move(src, dest)
 #递归删除文件
 shutil.rmtree(folder1, folder2)
- 压缩文件 
 压缩文件。将目录”/usr/local/project”压缩到”/home/mogl/test.tar.gz”
 压缩包支持类型:zip/tar/gztar/bztar- 1 - shutil.make_archive("/home/mogl/test", 'gztar', root_dir="/usr/local/project") 
glob
 glob模块提供Unix Shell规则的文件匹配功能1
2
3
4
5
6
7
8
9import glob
glob.glob('*.png')
glob.glob('[0-9].*')
#返回迭代器
files = glob.iglob('*.log')
for each_file in files:
    print each_file
shlex
 shlex模块提供简单的Unix Shell命令参数词法分析功能,可结合subprocess使用。1
2
3
4import shlex
shlex.split("ls -lht /tmp")
#['ls', '-lht', '/tmp']
argparse
 argparse是用于命令行参数解析的模块,功能非常强大,目前所用到的只是简单功能,直接上实例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import argparse
parser = argparse.ArgumentParser(description='descritption', epilog="author:mogl")
parser.add_argument('-d', '--directory', action='store_true', help='Only search directory')
parser.add_argument('-i', '--ignore-case', action='store_true', help='Ignore case search')
parser.add_argument('-S', '--srcport', help='sorce port', type=int, required=True)
parser.add_argument('-D', '--destport', help='dest port', type=int, default=80)
parser.add_argument('file_name', nargs='+', help='The file name')
args = parser.parse_args()
#获取参数值
print args.ignore_case
print args.srcport
print args.destport
#python test.py -S 124 test mogl
#False
#124
#80
#['test', 'mogl']
- 参数 
 参数可分为两种:- 选项参数(optional)
 parser.add_argument('-i', '--ignore-case', action='store_true', help='Ignore case search')
 选项参数默认使用-做前缀标识
- 位置参数(positional)
 parser.add_argument('file_name', nargs='+', help='The file name')
 
- 选项参数(optional)
- 选项参数解析 
 选项参数默认返回- None,可用- default参数指定默认值。如果该参数是必须的则使用- required=True
 - parser.add_argument('-i', '--ignore-case', action='store_true', help='Ignore case search')
 - parser.add_argument('-S', '--srcport', help='sorce port', type=int, required=True)- '-i', '--ignore-case'
 参数长短语法
- action='store_true'
 表明该参数不接受参数传递,即不接收诸如- -i test、- --ignore-case=true
- type=int
 若不使用- action='store_true'则可表明接受参数传递,使用- type指定传入类型(- type=int|str|complax)
- help='sorce port'
 该参数的说明
 
- 位置参数 
 若指定了位置参数,则运行程序时必须传入该参数才能运行
 - parser.add_argument('file_name', nargs='+', help='The file name')- nargs
 将多个参数关联在一起。- +将多个参数存到一个列表里,至少要有一个参数否则报错
 
- action 
 argparse默认设置6个action:- store
 保存参数值,可能会先将参数值转换成另一个数据类型。若没有显式指定动作,则默认为该动作。
- store_const
 保存一个被定义为参数规格一部分的值,而不是一个来自参数解析而来的值。这通常用于实现非布尔值的命令行标记。
- store_ture/store_false
 保存相应的布尔值。这两个动作被用于实现布尔开关。
- append
 将值保存到一个列表中。若参数重复出现,则保存多个值。
- append_const
 将一个定义在参数规格中的值保存到一个列表中。
- version
 打印关于程序的版本信息,然后退出
 
- store
re
re提供正则表达式匹配操作,是处理字符串最常用的库。
正则表达式语法
使用re库前,先大致了解正则表达式的基本语法,正好顺便总结一下有关正则表达式的内容。
| 符号 | 意义 | |||
|---|---|---|---|---|
| 基本关键字 | ||||
| . | 常规模式下匹配除 \n外的所有字符,DOTALL模式下\n也匹配 | |||
| ^ | 常规模式下匹配字符串开头,MULTILINE模式下匹配每行开头 | |||
| $ | 常规模式下匹配字符串结尾,MULTILINE模式下匹配行尾 | |||
| * | 匹配*前面内容零次或多次,贪婪匹配 | |||
| + | 匹配+前面内容零次或多次,贪婪匹配 | |||
| ? | 匹配?前面内容零次或1次 | |||
| {m} | 匹配{m}前面内容m次 | |||
| {m,n} | 匹配{m,n}前面内容m~n次 | |||
| *? +? ?? {m,n}? | * + ? {m,n}都是贪婪匹配,后面加上?后为非贪婪匹配 | |||
| [] | 匹配[]内字符集的任一字符, ^表示不匹配,-并用给出一段范围字符 | |||
| 单竖线 | 或,只匹配其中一个 | |||
| 分组关键字 | ||||
| (…) | 匹配括号内任意正则表达式并形成一个分组 | |||
| (?P <name>…) | 为符合匹配的分组命名 | |||
| (?#…) | 注释,(?#..)里的内容会被忽略 | |||
| (?=…) | 匹配结果后面的字符串需要满足表达式 ...。python_re_test——.*(?=_test)则匹配到字符串python_re | |||
| (?!…) | 匹配结果后面的字符串必须不满足表达式 ... | |||
| (?<=…) | 匹配结果前面的字符串需要满足表达式 ...。python_re_test——(?<=python_).*则匹配字符串re_test | |||
| (?<!…) | 匹配结果前面的字符串必须不满足表达式 ... | |||
| 特殊关键字 | ||||
| \d | 匹配数字,相当于[0-9] | |||
| \D | 匹配非数字,相当于[^0-9] | |||
| \s | 匹配空白字符,相当于[\t\r\n\f\v] | |||
| \S | 匹配非空白字符,相当于[^\t\r\n\f\v] | |||
| \w | 匹配字母或数字,相当于[0-9a-zA-Z] | |||
| \W | 匹配非字母或数字,相当于[^0-9a-zA-Z] | |||
| \b | 匹配字符串边界 | |||
| \B | 匹配非字符串边界 | |||
| \A | 匹配字符串开头 | |||
| \Z | 匹配字符串结尾 | 
re库flags参数
 Python的re库API中可指定flags参数,通过这些flags参数指定正则表达式选项通常使用类似re.I这样的简写,比如re.compile(pattern, [flags])函数——re.compile(pattern, re.I)。
| 符号 | 意义 | |||
|---|---|---|---|---|
| re.A | ASCII | 使\w\W\b\B\d\D匹配ASCII字符 | ||
| re.I | IGNORECASE | 忽略大小写 | ||
| re.L | LOCALE | 使\w\W\b\B匹配本地字符集 | ||
| re.M | MULTILINE | 多行模式, ^匹配每行开头,$匹配每行结尾 | ||
| re.X | VERBOSE | 详细模式,忽略空格和 #后面的注释 | ||
| re.U | UNICODE | 使\w\W\b\B\d\D匹配unicode字符集 | 
re库正则函数
- re.compile(pattern[, flags]) 
 将模式和标识编译成正则表达式对象,方便给- search()、- match()和- findall()等函数使用。- 1 
 2
 3
 4
 5- import re 
 pattern = re.compile(r'[0-9]+')
 print pattern.findall('abc123d')
 #123
- re.search(pattern, string[, flags]) 
 在字符串- string中查找匹配- pattern表达式的串,成功则返回MatchObject对象,失败则返回None- re.search (string[, pos[, endpos]]) 
 对于已编译的正则表达式对象,- search()函数可指定搜索的起始结束位置- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- import re 
 #使用compile()
 pattern = re.compile("a+")
 print pattern.search("aabcde").group(0) #=>aa
 print pattern.search("aabcde", 1).group(0) #=>a
 #不使用compile()
 regx = re.search(r'a+', 'aabcde')
 print regx.group(0) #=>aa
 
- re.match(pattern, string[, flags]) 
 在字符串- string开头位置查找匹配- pattern表达式的串(必须是开头位置)- re.match(string[, pos[, endpos]])
 同样对于已编译的正则对象可指定位置1 
 2
 3pattern = re.compile("a+") 
 print pattern.match('aabcde').group(0) #=>aa
 print pattern.match('xaabcde') #=>None
 
- re.match(string[, pos[, endpos]])
- re.findall(pattern, string[, flags]) 
 在字符串- string中查找所有匹配- pattern的串,成功则返回列表,失败则返回空列表。
 - re.search()和- re.match()仅匹配一次。- re.findall(string[, pos[, endpos]])
 同样对于已编译的正则对象可指定位置1 
 2
 3
 4
 5pattern = re.compile("\d+") 
 print pattern.search('ab12cd34').group(0) #=>12
 print pattern.match('ab12cd34') #=>None
 print pattern.findall('ab12cd34') #=>['12', '34']
 
- re.findall(string[, pos[, endpos]])
- re.finditer(pattern, string[, flags]) 
 - re.finditer()和- re.findall()类似,只是- re.finditer()返回一个迭代器对象。- 1 
 2
 3
 4
 5- pattern = re.compile("\d+") 
 for each_iter in piter:
 print each_iter.group(0)
 #=>12
 #=>34
- re.sub(pattern, rep_string, string[, count, flags]) 
- re.subn(pattern, rep_string, string[, count, flags])
 在字符串string中查找匹配pattern的字符串并用rep_string替换。rep_string可以是一个函数,成功则返回替换后的字符串,否则返回原字符串。
 re.subn()和re.sub()类似,只是re.subn()返回替换后的字符串和替换次数。1 
 2
 3pattern = re.compile(r'(name|full_name)') 
 pattern.sub('mogl', 'name test python re full_name')
 #=>'mogl test python re mogl'
MatchObject对象
 re.match()、re.search()和re.finditer()若成功匹配的话都是返回一个MatchObject对象。(re.findall()返回列表)
 MatchObject对象可调用几个函数:
- group():返回匹配的完整字符串
- groups():返回分组信息
- groupdict():返回所有命名分组字典
- start():返回匹配字符串的起始位置
- end():返回匹配字符串的结束位置
- span():返回起始位置和结束位置的元组
| 1 | import re | 
os
os模块提供统一的操作系统功能。
- os.getcwd() 
 获取当前工作目录
- os.chdir(path) 
 修改工作目录
- os.listdir(path) 
 列出path下所有文件/目录,不支持递归和通配符
- os.walk(path) 
 深度遍历path下所有文件/目录- 1 
 2- for root, dirs, files in os.walk('/tmp'): 
 print "root=%s, dirs=%s, files=%s" % (root, dirs, files)**
- os.mkdir(path) 
 创建目录,若path已存在则抛出异常
- os.makedirs(‘/path/subpath’) 
 递归创建多级目录,相当于Linux命令- mkdir -p
- os.rmdir(path) 
 删除空目录
- os.removedirs(path) 
 递归删除path下的子目录,目录非空则异常
- os.remove(file) 
 删除文件,若file为目录则抛出异常
- os.rename(path1, path2) 
 重命名
- os.renames(path1, path2) 
 重命名,会创建path2目标路径
- os.chmod(path, mode) 
 修改权限- 1 - os.chmod('/tmp/test', 0777)** 
- os.chown(path, uid, gid) 
 修改拥有者
- os.access(path, mode) 
 权限测试- 1 
 2
 3- os.access('/tmp/test.txt', os.W_OK)** 
 os.access('/tmp/test.txt', os.R_OK)**
 os.access('/tmp/test.txt', os.X_OK)**
os.path
os.path提供操作路径的函数。
- os.path.abspath(path) 
 获取绝对路径
- os.path.realpath(path) 
 软连接的真实路径
- os.path.basename(path) 
 获取文件名,以- /结尾的路径返回空
- os.path.dirname(path) 
 获取目录名
- os.path.exists(path) 
 判断- path路径是否存在
- os.path.isfile(path) / os.path.isdir(path) / os.path.islink(path) / os.path.ismount(path) 
 判断- path是否为文件/目录/软连接/挂载点
- os.path.split(path) 
 将- path切分为- (目录, 文件名)
- os.path.splitext(path) 
 将- path切分为- (目录/主文件名, 后缀名)
- os.path.join(path1, path2) 
 拼接路径
sys
sys模块,主要处理Python环境的变量使得程序与系统环境有交互。
- sys.argv[x]
 获取命令行参数列表。0表示程序名,1表示第一个命令行第一个参数,以此类推。
- sys.exit(num)
 程序退出状态码,sys.exit(0)表示正常退出。
- sys.path
 返回模块的搜索路径。
- sys.stdout / sys.stdin / sys.stderr
 标准输出/输入/错误输出
time
time模块主要提供和时间相关的函数。
- time.time()
 返回距离纪元(1970-01-01 00:00:00)开始的秒数,返回值为浮点数。
- time.ctime()
 返回字符串型易读的时间,诸如:Wed Oct 1 20:18:59 2016
- time.clock()
 返回当前进程消耗的CPU时间(秒)
- time.gmtime() / time.localtime() 
 - time.gmtime()和- time.localtime()的结果都是使用struct_time格式显示,可使用- time.asctime()转变成- time.ctime()的字符串格式显示。
 - time.gmtime()获取的是UTC时间,- time.localtime()获取的是当前时区的时间。在中国:- time.gmtime() = time.localtime() + 8hour- 1 
 2
 3
 4
 5
 6
 7
 8- time.gmtime() 
 #time.struct_time(tm_year=2016, tm_mon=10, tm_mday=5, tm_hour=15, tm_min=29, tm_sec=14, tm_wday=2, tm_yday=279, tm_isdst=0)
 time.localtime()
 #time.struct_time(tm_year=2016, tm_mon=10, tm_mday=5, tm_hour=23, tm_min=30, tm_sec=4, tm_wday=2, tm_yday=279, tm_isdst=0)
 time.asctime(time.localtime())
 #'Wed Oct 5 23:30:35 2016'
- time.strptime() 
 将字符串格式时间转成struct_time格式时间- 1 
 2- time.strptime(time.ctime()) 
 #time.struct_time(tm_year=2016, tm_mon=10, tm_mday=5, tm_hour=23, tm_min=37, tm_sec=17, tm_wday=2, tm_yday=279, tm_isdst=-1)
- time.strftime() 
 将时间格式化输出- 1 
 2- time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) 
 #'2016-10-05 23:39:23'
- time.sleep(num) 
 进程sleep时间
datetime
 datetime模块提供操作日期和时间函数。
 datetime模块常用的有四个类别,这些对象都是不可变对象:
- datetime.date:用于操作日期
- datetime.time:用于操作时分秒
- datetime.datetime:用于操作日期和时分秒
- datetime.timedelta:用于操作时间间隔
datetime.date
| 1 | from datetime import date | 
datetime.time
| 1 | import datetime | 
datetime.datetime
datetime.datetime和datetime.time差不多1
2
3
4
5
6
7
8start = datetime.datetime.now()
#2016-10-06 23:47:29.105713
end = datetime.datetime.now()
#2016-10-06 23:47:45.449751
print (end - start).seconds
#16
datetime.timedelta
 主要用于做时间的加减操作。1
2
3
4
5
6
7today = datetime.datetime.today()
#2016-10-06 23:41:46.170686
delta = datetime.timedelta(days=1)
yesterday = today - delta
#2016-10-05 23:41:46.170686
paramiko
 paramiko模块提供ssh远程登录等相关功能。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34import paramiko
def ssh_command(ip, username, passwd, cmd, port=22):
    """paramiko demo"""
    try:
    	ssh = paramiko.SSHClient()
    	#允许连接不在know_hosts文件中的主机
    	ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    	ssh.connect(ip, port, username, passwd, timeout=30)
    	stdin, stdout, stderr = ssh.exec_command(cmd)
    except Exception, e:
    	raise "%s ssh connect error: %s" % (ip, e)
    finally:
    	ssh.close()
    std_result = {'stdout': stdout.readlines(),
    			'stderr': stderr.readlines()
    			}
    return std_result
#paramiko模块还支持sftp传输功能
scp=paramiko.Transport((host_ip, ssh_port))
scp.connect(username=ssh_username, password=ssh_passowrd)
sftp=paramiko.SFTPClient.from_transport(scp)
#如果之前已有一个建立连接的ssh对象,则可直接复用该ssh连接对象
#sftp = paramiko.SFTPClient.from_transport(ssh.get_transport())
#sftp = ssh.open_sftp()
#下载文件
sftp.get('/tmp/remote_file','/tmp/local_file')
#上传文件
sftp.put('/home/local_file','/tmp/remote_file')
scp.close()
subprocess
 subprocess模块允许创建新进程并获取返回值/输出信息,常用来调用系统命令。
 常用已封装好的函数有三个:
- subprocess.call()
 返回exit code。不管exit code是什么都不会抛出异常。
- subprocess.check_call()
 返回exit code并检查exit code。exit code为0则成功,否则抛出subprocess.CalledProcessError异常。
- subprocess.check_output()
 返回输出信息且检查exit code。exit code不为0则抛出subprocess.CalledProcessError异常。1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21import subprocess 
 #结果相同,返回的是exit code
 subprocess.call(['echo', 'test'])
 subprocess.call("echo test", shell=True)
 subprocess.check_call(['echo', 'test'])
 #test
 #0
 #返回的是输出信息
 subprocess.check_output(['echo', 'test'])
 #'test\n'
 #可用shlex模块解析参数而不使用`shell=True`
 subprocess.call(shlex.split("echo test"))
 #test
 #0
 #忽略输出,只获取exit code
 with open(os.devnull, 'w') as devnull:
 exit_code = subprocess.call(["echo", "test"], stdout=devnull, stderr=devnull, shell=True)
subprocess.Popen()
 subprocess.call、subprocess.check_call和subprocess.check_output都是基于subprocess.Popen()的封装。在创建了Popen对象后,父进程不会主动等待子进程需要调用wait()方法使其等待。1
2
3
4
5subprocess.Popen('ps aux|grep ipython', shell=True).wait()
#命令输出
#=>mogl     28580  0.0  0.3  32568 15332 pts/26   Sl+  16:35   0:01 /usr/bin/python /usr/local/bin/ipython
#返回值
#=>0
 可使用subprocess.PIPE改变输入输出对象并获取子进程的更详细信息1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16child = subprocess.Popen('ps aux|grep ipython', shell=True, stdout=subprocess.PIPE)
child.pid
#25556
child.stdout.readlines()
#mogl     28580  0.0  0.3  32568 15332 pts/26   Sl+  16:35   0:01 /usr/bin/python /usr/local/bin/ipython
child.poll
#检查子进程是否已终止。没终止返回空,终止返回exit code
child.wait()
#0
child.returncode
#0
 subprocess.PIPE还可以将多个子进程的输入输出连接
 communicate()是Popen对象的方法,该方法会阻塞父进程,直到子进程完成。child2的输出也在PIPE中,需要调用child2.communicate()读取。1
2
3child1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
child2 = subprocess.Popen(["wc"], stdin=child1.stdout,stdout=subprocess.PIPE)
out = child2.communicate()
functools
 functools提供高阶函数功能。主要包含cmp_to_key、partial、reduce、total_ordering、update_wrapper和wraps这几个函数。
- functools.cmp_to_key(func) 
 - functools.cmp_to_key()是Python2.7新增的函数,用于将比较函数转成key函数,需要在接受key函数作为参数的函数中才使用。其实是为了兼容Python3,拿- sorted()函数为例:Python2版本的- sorted()函数支持- cmp参数来处理用户自定义的排序函数,但Python3后将- cmp参数移除了,所以需要使用到- cmp_to_key将自定义的排序函数转成key函数- 1 
 2
 3
 4
 5
 6
 7- #Python2 
 sorted([5, 2, 4, 1, 3], cmp=lambda x, y: y-x)
 #=>[5, 4, 3, 2, 1]
 #Python3
 sorted([5, 2, 4, 1, 3], key=cmp_to_key(lambda x, y: y-x))
 #=>[5, 4, 3, 2, 1]
- functools.total_ordering(cls) 
 - functools.total_ordering()也是Python2.7新增的函数,主要用于简化比较函数的写法。当某个类定义了- __eq__()方法,并且定义了- __lt__()、- __le__()、- __gt__()或- __ge__()方法中的其中一个,若使用- @total_ordering()装饰器,则该类会自动生成其他的比较方法。
 官方例子:- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- from functools import total_ordering 
 @total_ordering
 class Student:
 def __eq__(self, other):
 return ((self.lastname.lower(), self.firstname.lower()) ==
 (other.lastname.lower(), other.firstname.lower()))
 def __lt__(self, other):
 return ((self.lastname.lower(), self.firstname.lower()) <
 (other.lastname.lower(), other.firstname.lower()))
 print dir(Student)
 #=>['__doc__', '__eq__', '__ge__', '__gt__', '__le__', '__lt__', '__module__']
- functools.reduce(function, iterable) 
 - functools.reduce()和内置的- reduce()功能一样,使用- functools.reduce()也是为了兼容Python3。
- functools.partial(func[,*args][, keywords])** 
 - functools.partial()简单的说就是实现柯里化的。- 1 
 2
 3
 4
 5
 6
 7
 8- from functools import partial 
 def add(x, y):
 return x + y
 add_y = partial(add, 1)
 print add_y(1)
 #=>2
- functools.wraps(wrapped[, assigned][, updated]) 
 - functools.wraps()主要的作用是消除Python中装饰器带来的一些副作用。Python中使用装饰器,被装饰函数的- __name__属性会被改变,需要用- functools.wraps()进行修正。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- from functools import wraps 
 def decorator(func):
 #@wraps(func)
 def wrapper(*args, **kwargs):
 print "In decorator wrapper func."
 return func(*args, **kwargs)
 return wrapper
 @decorator
 def test():
 print "In test func."
 print test.__name__
 #=>wrapper
- functools.update_wrapper(wrapper, wrapped[, assigned][, updated]) 
 - functools.wraps()是- functools.update_wrapper()的简化版本,- functools.update_wrapper()功能更强大,默认会将被装饰函数的- functools.WRAPPER_ASSIGNMENTS(- __module__、- __name__、- __doc__)和- functools.WRAPPER_UPDATES(- __dict__)都复制给装饰函数。
 实际上面的装饰器代码可用- update_wrapper()写:- 1 
 2
 3
 4
 5
 6
 7- from functools import update_wrapper 
 def decorator(func):
 def wrapper(*args, **kwargs):
 print "In decorator wrapper func."
 return func(*args, **kwargs)
 return update_wrapper(wrapper, func)
smtplib
 smtplib模块用于发送邮件。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
def send_mail(send_list, subject, content):
	"""html/text邮件"""
	mail_host = "your_smtp_server_address"
	mail_user = 'your_email_user(xxx@gmail.com)'
	mail_passwd = 'your_email_password'
	mail_port = 25
	send_from = "your_send_from" + "<" + mail_user + ">"
	##TEXT邮件
	#msg = MIMEText(content, _subtype='plain', _charset='utf-8')
	##HTML邮件
	#msg = MIMEText(content, _subtype='html', _charset='utf-8')
	##带附件邮件
    msg = MIMEMultipart()
    #邮件正文
    msg.attach(MIMEText(content, _charset='utf-8'))
    #附件一
    att_1 = MIMEText(open('/tmp/attachment1.txt', 'rb').read(), 'base64', 'utf-8')
    att_1['Content-Type'] = 'application/octet-stream'
    #邮件中附件显示的文件名字
    att_1['Content-Disposition'] = 'attachment; filename=%s' % "附件1"
    msg.attach(att_1)
	msg['From'] = send_from
	msg['Subject'] = subject
	try:
		mail_server = smtplib.SMTP()
		mail_server.connect(mail_host, mail_port)
		mail_server.login(mail_user, mail_passwd)
		mail_server.sendmail(msg['From'], send_list, msg.as_string())
		mail_server.close()
		return True
	except Exception, e:
		print str(e)
		return False
requests
 requests是第三方模块,相比Python内置的urlib2更人性化。
 由于requests是第三方模块,需要使用pip进行安装,在一些版本中可能会在使用中出现SNIMissingWarning和InsecurePlatformWarning警告,可按以下方法安装。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#安装
yum install -y openssl-devel python-devel libffi-devel
pip install 'requests[security]'
#若在使用中出现SNIMissingWarning和InsecurePlatformWarning警告可
pip install pyopenssl ndg-httpsclient pyasn1
#若不想额外安装包可手动忽略警告
#关闭requests的https警告
try:
    from requests.packages.urllib3.exceptions import (
        SNIMissingWarning,
        InsecureRequestWarning,
        InsecurePlatformWarning
    )
    requests.packages.urllib3.disable_warnings(SNIMissingWarning)
    requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
    requests.packages.urllib3.disable_warnings(InsecurePlatformWarning)
except ImportError:
    pass
 requests常用方法。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48import requests
import json
url = 'https://github.com/timeline.json'
#GET请求(10s超时)
r = requests.get(url, timeout=10)
#文本方式显示
print r.text
#字节方式显示,中文显示为字符
print r.content
#显示编码 & 设置编码
print r.encoding
r.encoding = 'utf-8'
#响应状态码
r.status_code
#HTTP header
r.headers
r.headers['Content-Type']
#JSON化,失败会抛出异常
r.json()
#POST请求
headers = {
	'content-type': 'application/json',
	'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'
}
data = {
	"mobile": mobile,
	"templateId": template_id,
	"templateVariable": {
		self.mobile: {
			"secode": vcode
		}
	},
	"userName": user_name,
	"randomKey": random_key,
	"fingerprint": fingerprint
}
try:
	r = requests.post(url, data=json.dumps(data), headers=headers)
	result = r.json()
	#result = json.loads(r.content)
except Exception, err:
	raise err
hashlib
 hashlib模块实现各种hash算法。hashlib基于OpenSSL,支持md5、sha1、sha224、sha256、sha384和sha512等算法。
 基本用法。update()可多次调用,每次都会根据新增文本更新结果。1
2
3
4
5
6
7
8import hashlib
mystr = 'mogl'
mymd5 = hashlib.md5()
mymd5.update(mystr)
print mymd5.hexdigest()
#=>d2624edb33f3be2c461b1e95740b6b5c
 用new()方法通过字符串形式指定算法1
2
3
4
5
6
7import hashlib
import sys
hash_name = sys.argv[1]
myhash = hashlib.new(hash_name)
myhash.update(mystr)
print myhash.hexdigest()
multiprocessing
multiprocessing模块提供多进程编程。
- multiprocessing.Process 
 - Process类的原型- multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={})。每个- Process类会生成一个- process对象并在新的进程中运行。
 每个- process对象最多只能调用一次- start()方法,- join([timeout])方法会阻塞调用- process对象的进程等待子进程执行完毕。- group:仅为兼容- threading.Thread,通常为- None
- target:子进程要执行的函数
- name:进程名,默认为- Process-1、- Process-2...
- args:- target函数调用的参数
- kwargs:- target函数调用的字典参数- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22- from multiprocessing import Process 
 import os
 def child_run(name):
 print "Run in child process name: %s, pid: %s" % (name, os.getpid())
 if __name__ == '__main__':
 print "Parent process pid: %s" % os.getpid()
 print "Creating child process..."
 #注意args参数中必须有,
 multi_proc = Process(target=child_run, args=('child_test',))
 #设置daemon属性
 #multi_proc.daemon = True
 print "Starting child process..."
 multi_proc.start()
 multi_proc.join()
 print "Process end."
 #Parent process pid: 12198
 #Creating child process...
 #Starting child process...
 #Run in child process name: child_test, pid: 12199
 #Process end.- 多进程并行运行。每个子进程都是先 - start(),最后在一起- join()。若对每个- process对象都一起执行- start()和- join()则变成顺序执行而非并发执行。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22- from multiprocessing import Process 
 import os
 def child_run(name):
 print "Run in child process name: %s, pid: %s" % (name, os.getpid())
 if __name__ == '__main__':
 names = ['mo', 'guo', 'liang', 'mogl']
 proc_list = []
 print "Parent process pid: %s" % os.getpid()
 for name in names:
 multi_proc = Process(target=child_run, args=(name,))
 proc_list.append(multi_proc)
 multi_proc.start()
 for each_child_proc in proc_list:
 each_child_proc.join()
 #Parent process pid: 14516
 #Run in child process name: mo, pid: 14517
 #Run in child process name: guo, pid: 14518
 #Run in child process name: liang, pid: 14519
 #Run in child process name: mogl, pid: 14520
 
- multiprocessing.Lock 
 - multiprocessing.Lock提供锁功能,当多进程需要访问共享资源时,可用锁来避免冲突。使用锁的话多进程并行则会受到锁的限制。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41- from multiprocessing import Process, Lock 
 import os
 def printer(string):
 print "In printer, string: %s, pid: %s" % (string, os.getpid())
 def printer_lock(string, lock):
 lock.acquire()
 print "In printer, string: %s, pid: %s" % (string, os.getpid())
 lock.release()
 if __name__ == '__main__':
 proc_list = []
 names = ['mo', 'guo', 'liang', 'mogl']
 print "Parent pid: %s" % os.getpid()
 for each_name in names:
 multi_proc = Process(target=printer, args=(each_name,))
 proc_list.append(multi_proc)
 multi_proc.start()
 lock = Lock()
 for each_name in names:
 multi_proc_lock = Process(target=printer_lock, args=(each_name, lock))
 proc_list.append(multi_proc_lock)
 multi_proc_lock.start()
 for each_proc in proc_list:
 each_proc.join()
 #Parent pid: 9313
 #In printer, string: mo, pid: 9314
 #In printer, string: liang, pid: 9316
 #In printer, string: guo, pid: 9315
 #In printer, string: mogl, pid: 9317
 #In printer, string: mo, pid: 9318
 #In printer, string: guo, pid: 9319
 #In printer, string: liang, pid: 9320
 #In printer, string: mogl, pid: 9321
- multiprocessing.Queue & multiprocessing.Pipe 
 - multiprocessing支持两种进程间通信方式:- Queue、- PIPE,- Queue是进程安全的。- multiprocessing.Queue 
 使用- Queue实现进程间通信,进程A使用- put()方法将数据存入- Queue,进程B使用- get()方法从- Queue中读取数据。
 - put()、- get()方法都有两个参数:- block、- timeout,若- block=False,Queue为- full/- empty则抛出异常,若设置了- timeout则阻塞等待再一次- put/- get。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28- from multiprocessing import Process, Queue 
 import os
 def write_queue(queue):
 print "In write_queue pid: %s" % os.getpid()
 queue.put(['mogl'], block=False)
 def read_queue(queue):
 print "In read_queue pid: %s" % os.getpid()
 print queue.get(block=False)
 if __name__ == '__main__':
 print "Parent pid: %s" % os.getpid()
 queue = Queue()
 write_proc = Process(target=write_queue, args=(queue,))
 write_proc.start()
 read_proc = Process(target=read_queue, args=(queue,))
 read_proc.start()
 write_proc.join()
 read_proc.join()
 #Parent pid: 18383
 #In write_queue pid: 18384
 #In read_queue pid: 18385
 #['mogl']
- multiprocessing.Pipe 
 - Pipe()方法会返回- (c1, c2)代表一个管道的两端,默认- Pipe()的- duplex=True表示全双工管道,即管道的任意一端都可发送和接收信息。若- duplex=False则- c1只负责接收,- c2只负责发送。当调用- recv()方法从管道读取消息时候,若管道一端无消息,- recv()则会一直阻塞。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31- from multiprocessing import Process, Pipe 
 import os
 def process_one(pipe):
 pipe.send('hello, process_one send message.')
 print 'process_one receive message:', pipe.recv()
 print "process_one pid:", os.getpid()
 def process_two(pipe):
 print 'process_two receive message:', pipe.recv()
 pipe.send('hello, process_two send message.')
 print "process_two pid:", os.getpid()
 if __name__ == '__main__':
 pipe = Pipe()
 print "main pid:", os.getpid()
 pro1 = Process(target=process_one, args=(pipe[0],))
 pro2 = Process(target=process_two, args=(pipe[1],))
 pro1.start()
 pro2.start()
 pro1.join()
 pro2.join()
 #process_one发送消息后recv,由于管道一端无消息而阻塞,故先打印process_two的内容
 #main pid: 14215
 #process_two receive message: hello, process_one send message.
 #process_two pid: 14217
 #process_one receive message: hello, process_two send message.
 #process_one pid: 14216
 
- multiprocessing.Pool 
 Python多进程支持进程池,使用- multiprocessing.Pool能创建一个进程池可指定进程数量,当请求提交给pool后,若pool没满则可创建新进程处理该请求,若已满则等待空闲后再处理。
 进程池中进程的创建可通过- apply_async(func[, args[, kwds[, callback]]])或- apply(func[, args[, kwds]])方法。- apply_async()是非阻塞,- apply()是阻塞(进程池中一个进程执行完才会执行下一个)。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24- from multiprocessing import Pool 
 import os
 import time
 import random
 def child_process_task(name):
 print "Running task %s, pid %s" % (name, os.getpid())
 start_time = time.time()
 time.sleep(random.random() * 3)
 end_time = time.time()
 print "Task %s is over and runs %0.2f seconds." % (name, (end_time - start_time))
 if __name__ == '__main__':
 print "Parrent process pid %s" % os.getpid()
 #创建进场池。限制并发数量:child_pool = Pool(processes=4)
 child_pool = Pool()
 for eachpid in range(5):
 #批量创建子进场(指定执行函数及其参数)
 child_pool.apply_async(child_process_task, args=(eachpid,))
 print "Waitting for all child process done..."
 #调用join()前必须先调用close()。close()关闭pool不在接受新请求。join()等待所有子进程结束
 child_pool.close()
 child_pool.join()
 print "All process is done."
MySQLdb
 MySQLdb是第三方模块,用于连接及操作MySQL。
 一般先使用MySQLdb.connect()方法创建连接对象,该连接对象支持事务操作,即允许commit()和rollback()。然后使用cursor()方法获取游标对象,该对象做两类操作——执行sql和获取查询结果。最后操作完数据库后需要调用close()方法关闭相关对象。
执行sql
| 1 | import MySQLdb | 
 更新(update)、删除(delete)和插入(insert)等支持事务操作。1
2
3
4
5
6
7
8
9
10
11
12
13
14insert_sql = 'INSERT INTO STUDENT(NAME, AGE, GENDER)\
    VALUES ("%s", "%s", "%s")' % ('mogl', 10, 'male')
try:
    db_conn = MySQLdb.connect(host='localhost', user='root', passwd='fate', db='test', port=3306)
    db_cur = db_conn.cursor()
    db_cur.execute(insert_sql)
    db_conn.commit()
except Exception, e:
    db_conn.rollback()
    raise e
finally:
    db_cur.close()
    db_conn.close()
获取查询结果
 使用fetchall()返回select查询的所有结果,默认每行结果以元组形式返回,可使用cursorclass=MySQLdb.cursors.DictCursor返回字典形式。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15select_sql = "select * from STUDENT"
try:
    db_conn = MySQLdb.connect(host='localhost', user='root', passwd='fate', db='test', port=3306)
    db_cur = db_conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)
    db_cur.execute(select_sql)
    select_result = db_cur.fetchall()
except Exception, e:
    raise e
finally:
    db_cur.close()
    db_conn.close()
for row in select_result:
    print row['NAME'], row['AGE'], row['GENDER']
ConfigParser
 ConfigParser模块用来解析类似ini格式的配置文件。
 ini格式配置文件大致如下:
- section:- [test1]、- [test2]
- option:- section下所有的键
- items:- section下所有的键值对- 1 
 2
 3
 4
 5
 6
 7
 8
 9- #test.cfg 
 [test1]
 name = mogl
 passwd = 1234
 [test2]
 name = moguoliang
 passwd = 4321
| 1 | import ConfigParser | 
lxml
lxml用于解析xml或html,用法比较复杂,这里只记录自己用到的简单功能。
- cssselect() - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35- from lxml import html 
 #实例一
 page = '<img class="BDE_Image" src="http://test.com/test.jpg" width="560" height="323">'
 doc = html.fromstring(page)
 for index, content in enumerate(doc.cssselect('img.BDE_Image')):
 img_src = content.attrib['src']
 print index, img_src
 #0 http://test.com/test.jpg
 #实例二
 page = """
 <div class="buyer-name">mogl</div>
 <span class="item-price" src='http://test.com/test.html'>$2.9</span>
 <span class="item-price" src='http://test.com/test2.html'>$3.0</span>
 """
 htmlDoc = html.fromstring(page)
 buyers = htmlDoc.cssselect('div.buyer-name')
 prices = htmlDoc.cssselect('span.item-price')
 for eachBuyer in htmlDoc.cssselect('div.buyer-name'):
 print "buyer:", eachBuyer.text_content()
 for eachPrice in htmlDoc.cssselect('span.item-price'):
 print eachPrice.text_content()
 print eachPrice.attrib['src']
 #buyer: mogl
 #$2.9
 #http://test.com/test.html
 #$3.0
 #http://test.com/test2.html
- xpath 
 先简单记录- xpath的路径表达式:
| 表达式 | 实例 | 意义 | ||
|---|---|---|---|---|
| / | xpath(‘/div’) | 从根节点选取 div节点 | ||
| // | xpath(‘//div’) | 选取所有 div节点 | ||
| . | xpath(‘./div’) | 选取当前节点下的 div节点 | ||
| .. | xpath(‘..’) | 选取父节点 | ||
| @ | xpath(‘//@class’) | 选取属性 | 
| 1 | from lxml import html | 
BeautifulSoup
 BeautifulSoup模块和lxml类似都是用来解析HTML/XML的。该模块是是第三方模块需要安装。1
$> pip install beautifulsoup4
 为了方便记录,就以以下的HTML代码为解析例子1
2
3
4
5html = """
<html><head><title>The BeautifulSoup test</title></head>
<a class="mnav" href="http://news.mogl.com" name="news">新闻</a>
<img src=http://www.mogl.com/img/test.png width=270 height=129>
"""
 默认Python会使用内置的解析器进行解析,但速度较慢,这里使用lxml来进行解析(需要先装lxml)。1
2
3
4
5
6
7from bs4 import BeautifulSoup
import re
#创建BeautifulSoup对象
soup = BeautifulSoup(html, 'lxml')
#格式化输出
print soup.prettify('utf-8')
Tag——标签
 Tag是HTML中的标签,诸如title和a等。BeautifulSoup对Tag的处理主要包含三种:
- name
- string
- attrs
 获取整个Tag1
2
3
4
5
6
7
8print soup.title
print soup.head
print soup.a
print soup.img
#<title>The BeautifulSoup test</title>
#<head><title>The BeautifulSoup test</title></head>
#<a class="mnav" href="http://news.mogl.com" name="news">新闻</a>
#<img height="129" src="http://www.mogl.com/img/test.png" width="270"/>
 name是获取Tag的类型1
2
3
4print soup.title.name
print soup.a.name
#title
#a
 string是获取Tag标签中的文本内容1
2
3
4print soup.title.string
print soup.a.string
#The BeautifulSoup test
#新闻
 attrs是获取Tag标签中的属性1
2
3
4
5
6print soup.a.attrs
#{'href': 'http://news.mogl.com', 'class': ['mnav'], 'name': 'news'}
print soup.a['href']
#http://www.mogl.com/img/test.png
print soup.img.get('src')
#http://www.mogl.com/img/test.png
find_all——搜索
 find_all()是搜索当前tag的所有节点,返回符合条件的tag对象list。
 find_all()可对tag.name和tag.attrs进行搜索,还支持对使用re的正则匹配。1
2
3
4
5
6
7
8print soup.find_all('a')
#[<a class="mnav" href="http://news.mogl.com" name="news">新闻</a>]
print soup.find_all(['a', 'img'])
#[<a class="mnav" href="http://news.mogl.com" name="news">新闻</a>, <img height="129" src="http://www.mogl.com/img/test.png" width="270"/>]
print soup.find_all(re.compile(r'^a|^i'))
#[<a class="mnav" href="http://news.mogl.com" name="news">新闻</a>, <img height="129" src="http://www.mogl.com/img/test.png" width="270"/>]
 对tag.attrs进行搜索。当对HTML的class属性搜索时,为避免与Python内置的class关键字冲突,使用class_。1
2
3
4
5
6
7
8
9print soup.find_all('a', class_="mnav")
#[<a class="mnav" href="http://news.mogl.com" name="news">新闻</a>]
print soup.find_all(href=re.compile('mogl.com'), class_="mnav")
#[<a class="mnav" href="http://news.mogl.com" name="news">新闻</a>]
for num, each_tag in enumerate(soup.find_all('img')):
    print num, each_tag['width']
#0 270