glob

glob 模块是最简单的模块之一, 内容非常少, 用它可以查找符合特定规则的文件路径名, 就像在 windows 下使用文件搜索功能一样, 查找文件只用到三个匹配符: *, ?, [], * 匹配 0 个或多个字符, ? 匹配单个字符, [] 匹配指定范围内的字符 (如 [0-9]匹配数字).

glob.glob

返回所有匹配的文件路径列表, 它只有一个参数 pathname, 定义了文件路径匹配规则, 这里可以是绝对路径, 也可以是相对路径, 下面是使用 glob.glob 的例子:

import glob

# 获取指定目录下的所有图片
print glob.glob(r"E:\Picture\*\*.jpg")

# 获取上级目录的所有.py文件
print glob.glob(r'../*.py')  # 相对路径


glob.iglob

与 glob.glob 类似, 但它获取的是一个可迭代对象, 使用它可以逐个获取匹配的文件路径名 (类似 rang 与 xrang 的区别).

下面是一个简单的例子:

import glob
# 父目录中的.py文件
f = glob.iglob(r'../*.py')
print f  # <generator object iglob at 0x00B9FF80>

for py in f:
    print py


shutil

High-level file operations 高级的文件操作模块, 提供了一些易操作的文件移动复制打包压缩解压API.

API 功能
copyfileobj(fsrc, fdst[, length=16*1024]) copy 文件内容到另一个文件, 可以 copy 指定大小的内容
copyfile(src, dst) copy 文件内容, 是不是感觉上面的文件复制很麻烦? 还需要自己手动用 open 函数打开文件, 在这里就不需要了, 事实上, copyfile 调用了 copyfileobj
copymode(src,dst) 仅 copy 权限, 不更改文件内容, 组和用户
copystat(src,dst) 复制所有的状态信息, 包括权限, 组, 用户, 时间等
copy(src,dst) 复制文件的内容以及权限, 先 copyfile 后 copymode
copy2(src,dst) 复制文件的内容以及文件的所有状态信息, 先 copyfile 后 copystat
copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,ignore_dangling_symlinks=False) 递归的复制文件内容及状态信息
rmtree(path, ignore_errors=False, onerror=None) 递归地删除文件
move(src, dst) 递归的移动文件
make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, dry_run=0, owner=None, group=None, logger=None) 压缩打包
base_name: 压缩打包后的文件名或者路径名
format: 压缩或者打包格式 "zip"、"tar"、"bztar"、"gztar"
root_dir: 将哪个目录或者文件打包 (也就是源文件)

collections

collections 是 Python 内置的一个集合模块, 在 Python 内置数据类型的基础上, 又提供了几个额外的数据类型供我们使用.

namedtuple

如果看到一个 tuple (1, 2), 很难看出这是用来表示一个坐标的, 这时, namedtuple 就派上了用场:

from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)



namedtuple 是一个函数, 它用来创建一个自定义的 tuple 对象, 并且规定了 tuple 元素的个数, 并可以用名称而不是索引来引用 tuple 的某个元素.

这样一来, 我们用 namedtuple 可以很方便地定义一种数据类型, 它具备 tuple 的不变性, 又可以根据属性来引用, 使用十分方便.

可以验证创建的 Point 对象是 tuple 的一种子类:

>>> isinstance(p, Point)
True
>>> isinstance(p, tuple)
True


deque

使用 list 存储数据时, 按索引访问元素很快, 但是插入和删除元素就很慢了, 因为 list 是线性存储, 数据量大的时候, 插入和删除效率很低; 而 deque 是为了高效实现插入和删除操作的双向列表.

deque 其实是 double-ended queue 的缩写, 翻译过来就是双端队列, 它最大的好处就是实现了从队列头部快速增加和取出对象: popleft()appendleft().

关于 dequelist 的差别参考 wiki: vector、deque、list 三者的区别

Counter

Counter 是一个简单的计数器, 例如, 统计字符出现的个数:

from collections import Counter
c = Counter()
for ch in 'programming':
    c[ch] = c[ch] + 1



结果:

>>> c
Counter({'g': 2, 'm': 2, 'r': 2, 'a': 1, 'i': 1, 'o': 1, 'n': 1, 'p': 1})



Counter 实际上也是 dict 的一个子类, 上面的结果可以看出, 字符 'g'、'm'、'r' 各出现了两次, 其他字符各出现了一次.

OrderedDict

在 Python 中, dict 这个数据结构由于 hash 的特性, 是无序的, 这在有的时候会给我们带来一些麻烦, 幸运的是, collections 模块为我们提供了 OrderedDict, 当你要获得一个有序的字典对象时, 用它就对了.

from collections import OrderedDict
d = dict([('a', 1), ('b', 2), ('c', 3)])



结果:

d # dict Key是无序的
{'a': 1, 'c': 3, 'b': 2}



改用 OrderedDict:

od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])



结果:

od # OrderedDictKey是有序的
OrderedDict([('a', 1), ('b', 2), ('c', 3)])



注意, OrderedDict 的 Key 会按照插入的顺序排列, 不是Key本身排序.

defaultdict

使用 dict 时, 如果引用的 Key 不存在, 就会抛出 KeyError. 如果希望 key 不存在时, 返回一个默认值, 就可以用 defaultdict:

from collections import defaultdict
dd = defaultdict(lambda: 'N/A')
dd['key1'] = 'abc'



结果:

dd['key1'] # key1 存在
'abc'

dd['key2'] # key2不存在, 返回默认值
'N/A'



注意默认值是调用函数返回的, 而函数在创建 defaultdict 对象时传入.

docx

Python DocX 目前是 Python OpenXML 的一部分, 你可以用它打开 Word 2007 及以后的文档, 而用它保存的文档可以在 Microsoft Office 2007/2010, Microsoft Mac Office 2008, Google Docs, OpenOffice.org 3, and Apple iWork 08 中打开.

from docx import Document
from docx.shared import Inches

document = Document()

document.add_heading('Document Title', 0)

p = document.add_paragraph('A plain paragraph having some ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True

document.add_heading('Heading, level 1', level=1)
document.add_paragraph('Intense quote', style='IntenseQuote')

document.add_paragraph(
    'first item in unordered list', style='ListBullet'
)
document.add_paragraph(
    'first item in ordered list', style='ListNumber'
)

document.add_picture('monty-truth.png', width=Inches(1.25))

table = document.add_table(rows=1, cols=3)
hdr_cells = table.rows[0].cells
hdr_cells[0].text = 'Qty'
hdr_cells[1].text = 'Id'
hdr_cells[2].text = 'Desc'
for item in recordset:
    row_cells = table.add_row().cells
    row_cells[0].text = str(item.qty)
    row_cells[1].text = str(item.id)
    row_cells[2].text = item.desc

document.add_page_break()

document.save('demo.docx')


xlrd/xlwt

传说中 python 操作 ms office 功能最强大的是 win32com (据说只要人工能操作的它都能实现, 未尝试尚不知道真假), 不过对于比较简单的需求显得有些小题大作. 那么来看下简单的, 分别是 xlrd 和 xlwt 模块.

xlrd

# 导入
import xlrd
# 打开 excel
data = xlrd.open_workbook('demo.xls')  # 注意这里的 workbook 首字母是小写
# 查看文件中包含sheet的名称
data.sheet_names()
# 得到第一个工作表, 或者通过索引顺序 或 工作表名称
table = data.sheets()[0]
table = data.sheet_by_index(0)
table = data.sheet_by_name(u'Sheet1')
# 获取行数和列数
nrows = table.nrows
ncols = table.ncols
# 获取整行和整列的值 (数组)
table.row_values(i)
table.col_values(i)
# 循环行,得到索引的列表
for rownum in range(table.nrows):
    print table.row_values(rownum)
# 单元格
cell_A1 = table.cell(0, 0).value
cell_C4 = table.cell(2, 3).value
# 分别使用行列索引
cell_A1 = table.row(0)[0].value
cell_A2 = table.col(1)[0].value


xlwt

# 导入 xlwt
import xlwt
# 新建一个 excel 文件
file = xlwt.Workbook()  # 注意这里的Workbook首字母是大写, 无语吧
# 新建一个 sheet
table = file.add_sheet('sheet name')
# 写入数据 table.write(行, 列, value)
table.write(0, 0, 'test')
# 如果对一个单元格重复操作, 会引发
# returns error:
# Exception: Attempt to overwrite cell:
# sheetname=u'sheet 1' rowx=0 colx=0
# 所以在打开时加 cell_overwrite_ok=True 解决
table = file.add_sheet('sheet name', cell_overwrite_ok=True)
# 保存文件
file.save('demo.xls')
# 另外, 使用 style
style = xlwt.XFStyle()  # 初始化样式
font = xlwt.Font()  # 为样式创建字体
font.name = 'Times New Roman'
font.bold = True
style.font = font  # 为样式设置字体
table.write(0, 0, 'some bold Times text', style)  # 使用样式
# xlwt 允许单元格或者整行地设置格式. 还可以添加链接以及公式. 可以阅读源代码, 那里有例子:
# dates.py, 展示如何设置不同的数据格式
# hyperlinks.py, 展示如何创建超链接 (hint: you need to use a formula)
# merged.py, 展示如何合并格子
# row_styles.py, 展示如何应用Style到整行格子中.


tablib

tablib 也可以用来导出 xls、csv、yaml 等格式, 部分功能依赖于 xlwt, 基本上可以认为 tablib 是对 xlwt 的再封装.

Tablib is partially dependent on the pyyaml, simplejson, and xlwt modules. To reduce installation issues, fully integrated versions of all required libraries are included in Tablib.

import tablib
import os

# 创建 dataset, 方法 1
dataset1 = tablib.Dataset()
header1 = ('ID', 'Name', 'Tel', 'Age')
dataset1.headers = header1
dataset1.append([1, 'zhangsan', 13711111111, 16])
dataset1.append([2, 'lisi',     13811111111, 18])
dataset1.append([3, 'wangwu',   13911111111, 20])
dataset1.append([4, 'zhaoliu',  15811111111, 25])
print('dataset1:', os.linesep, dataset1, os.linesep)

# 创建 dataset, 方法 2
header2 = ('ID', 'Name', 'Tel', 'Age')
data2 = [
    [1, 'zhangsan', 13711111111, 16],
    [2, 'lisi',     13811111111, 18],
    [3, 'wangwu',   13911111111, 20],
    [4, 'zhaoliu',  15811111111, 25]
]
dataset2 = tablib.Dataset(*data2, headers = header2)
print('dataset2: ', os.linesep, dataset2, os.linesep)

# 增加行
dataset1.append([5, 'sunqi', 15911111111, 30])  # 添加到最后一行的下面
dataset1.insert(0, [0, 'liuyi', 18211111111, 35])  # 在指定位置添加行
print('增加行后的 dataset1: ', os.linesep, dataset1, os.linesep)

# 删除行
dataset1.pop()  # 删除最后一行
dataset1.lpop()  # 删除第一行
del dataset1[0:2]  # 删除第 [0,2) 行数据
print('删除行后的 dataset1:', os.linesep, dataset1, os.linesep)

# 增加列
# 现在 dataset1 就剩两行数据了
dataset1.append_col(('beijing', 'shenzhen'), header='city')  # 增加列到最后一列
dataset1.insert_col(2, ('male', 'female'), header='sex')  # 在指定位置添加列
print('增加列后的 dataset1: ', os.linesep, dataset1, os.linesep)

# 删除列
del dataset1['Tel']
print('删除列后的 dataset1: ', os.linesep, dataset1, os.linesep)

# 获取各种格式的数据
print('yaml format: ', os.linesep ,dataset1.yaml, os.linesep)
print('csv format: ' , os.linesep ,dataset1.csv , os.linesep)
print('tsv format: ' , os.linesep ,dataset1.tsv , os.linesep)

# 导出到Excel表格中
dataset1.title = 'dataset1'  # 设置Excel中表单的名称
dataset2.title = 'dataset2'
myfile = open('mydata.xlsx', 'wb')
myfile.write(dataset1.xlsx)
myfile.close()

# 如果有多个 sheet 表单, 使用 DataBook 就可以了
myDataBook = tablib.Databook((dataset1, dataset2))
myfile = open(myfile.name, 'wb')  # excel 表有二进制数据, 所以必须要用二进制模式打开文件, 即 'wb'
myfile.write(myDataBook.xlsx)
myfile.close()


calendar

calendar 模块的函数都是日历相关的, 例如打印某月的字符月历.

星期一是默认的每周第一天, 星期天是默认的最后一天. 更改设置需调用 calendar.setfirstweekday() 函数. 模块包含了以下内置函数:

函数 描述
calendar.calendar(year, w=2, l=1, c=6) 返回一个多行字符串格式的 year 年年历;
3 个月一行, 间隔距离为 c.
每日宽度间隔为 w 字符.
每行长度为 21*w+18+2*c.
l 是每星期行数.
calendar.firstweekday( ) 返回当前每周起始日期的设置.
默认情况下, 首次载入 caendar 模块时返回 0, 即星期一.
calendar.isleap(year) 是闰年返回 True, 否则为 false.
calendar.leapdays(y1, y2) 返回在 Y1, Y2 两年之间的闰年总数.
calendar.month(year, month, w=2, l=1) 返回一个多行字符串格式的 year 年 month 月日历;
两行标题, 一周一行.
每日宽度间隔为 w 字符.
每行的长度为 7*w+6. l 是每星期的行数.
calendar.monthcalendar(year, month) 返回一个整数的单层嵌套列表.
每个子列表装载代表一个星期的整数.
year 年 month 月外的日期都设为 0;
范围内的日子都由该月第几日表示, 从 1 开始.
calendar.monthrange(year, month) 返回两个整数.
第一个是该月的星期几的日期码;
第二个是该月的日期码.
日从 0 (星期一) 到 6 (星期日); 月从 1 到 12.
calendar.prcal(year, w=2, l=1, c=6) 相当于 print calendar.calendar(year,w,l,c).
calendar.prmonth(year, month, w=2, l=1) 相当于 print calendar.calendar (year, w, l, c).
calendar.setfirstweekday(weekday) 设置每周的起始日期码. 0 (星期一) 到 6 (星期日).
calendar.timegm(tupletime) 和 time.gmtime 相反: 接受一个时间元组形式,
返回该时刻的时间辍 (1970纪元后经过的浮点秒数).
calendar.weekday(year, month, day) 返回给定日期的日期码. 0 (星期一) 到6 (星期日).
月份为 1 (一月) 到 12 (12月).