10.1.操作系统接口

import os 一定要使用import os而非from os import * 原因:防止内建的open()函数被os.open()隐式替换掉 内置的dir()和help()函数可用作交互式的辅助工具

1
2
3
4
dir(os)
<返回由模块的所有函数组成的列表>
help(os)
<返回根据模块文档字符串创建的详细说明页面>

对于日常文件和目录管理任务,shutil模块提供了易用的高层级接口

10.2.文件通配符

glob模块提供了一个在目录中使用通配符搜索创建文件列表的函数

示例如下:

1
2
3
import glob
glob.glob('*.py')
['primes.py', 'random.py', 'quote.py']

10.3.命令行参数

参数是通过列表形式储存在sys模块的argv属性中 import sys来引入 argparse模块argparse 模块提供了一种更复杂的机制来处理命令行参数。 以下脚本可提取一个或多个文件名并可选择要显示的行数:(要用自己看)

1
2
3
4
5
6
7
8
9
import argparse

parser = argparse.ArgumentParser(
    prog='top',
    description='Show top lines from each file')
parser.add_argument('filenames', nargs='+')
parser.add_argument('-l', '--lines', type=int, default=10)
args = parser.parse_args()
print(args)

当通过 python top.py --lines=5 alpha.txt beta.txt 在命令行运行时,该脚本会将 args.lines 设为 5 并将 args.filenames 设为 ['alpha.txt', 'beta.txt']。

10.4.错误输出重定向和程序终止

sys模块的stdin,stdout,stderr属性,其中stderr在发出警告和错误信息很有用 终止脚本:sys.exit()

10.5.字符串模式匹配

re模块为高级表达式提供正则表达式工具

1
2
3
4
5
import re
re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
'cat in the hat'
1
2
'tea for too'.replace('too', 'two')
'tea for two'

正则表达式是的,yield 和普通函数中的 return 最大的不同在于:yield 不会让函数彻底结束,而是会让函数“暂停”,以后还能从暂停的位置继续执行。

这就是它最特别的地方。

正则含义
r''Python 原始字符串
\b单词边界
[a-z]任意一个小写字母
*0 次或多次
+1 次或多次
()捕获组
\1引用第一个捕获组
findall()找出所有匹配内容
sub()查找并替换

10.6.数字

math模块:众多数学方法 random:随机选择工具 statistics:计算数值数据的基本统计属性:例如均值,中位数,方差等等

10.7.互联网访问

挺多的,最简单的两个 urllib.request 用于从URL检索数据,以及 smtplib 用于发送邮件

10.8.日期和时间

datatime模块

10.9.数据压缩

常见的数据存档和压缩格式由模块直接支持,包括:zlib, gzip, bz2, lzma, zipfile 和 tarfile

10.10.性能测试

10.10. 性能测量

一些 Python 用户对了解同一问题的不同方法的相对性能产生了浓厚的兴趣。Python 提供了一种可以立即回答这些问题的测量工具。

例如,元组封包和拆包功能相比传统的交换参数可能更具吸引力。timeit 模块可以快速演示在运行效率方面一定的优势:

1
2
3
4
5
from timeit import Timer
Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
0.57535828626024577
Timer('a,b = b,a', 'a=1; b=2').timeit()
0.54962537085770791

与 timeit 的精细粒度级别相反, profile 和 pstats 模块提供了用于在较大的代码块中识别时间关键部分的工具。

10.11.质量控制(写测试)

这个感觉会有点用

开发高质量软件的一种方法是在开发过程中为每个函数编写测试,并在开发过程中经常运行这些测试。

doctest 模块提供了一个工具,用于扫描模块并验证程序文档字符串中嵌入的测试。测试构造就像将典型调用及其结果剪切并粘贴到文档字符串一样简单。这通过向用户提供示例来改进文档,并且它允许 doctest 模块确保代码与文档保持一致:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def average(values):
    """计算数字列表的算术平均值

    >>> print(average([20, 30, 70]))
    40.0
    """
    return sum(values) / len(values)

import doctest
doctest.testmod()   # 自动验证嵌入式测试

unittest 模块不像 doctest 模块那样易于使用,但它允许在一个单独的文件中维护更全面的测试集:

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

class TestStatisticalFunctions(unittest.TestCase):

    def test_average(self):
        self.assertEqual(average([20, 30, 70]), 40.0)
        self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
        with self.assertRaises(ZeroDivisionError):
            average([])
        with self.assertRaises(TypeError):
            average(20, 30, 70)

unittest.main()  # 从命令行调用时会执行所有测试

10.12.内置电池

Python 有"自带电池"的理念。通过其包的复杂和强大功能可以最好地看到这一点。例如:

  • xmlrpc.client 和 xmlrpc.server 模块使得实现远程过程调用变成了小菜一碟。 尽管存在于模块名称中,但用户不需要直接了解或处理 XML。
  • email 包是一个用于管理电子邮件消息的库,包括 MIME 和其他基于 RFC 5322 的消息文档。 不同于实际发送和接收消息的 smtplib 和 poplib,email 包提供用于构建或解码复杂消息结构(包括附件)以及实现互联网编码格式和标头协议的完整工具集。
  • json 包为解析这种流行的数据交换格式提供了强大的支持。 csv 模块支持以逗号分隔值格式直接读取和写入文件,这种格式通常为数据库和电子表格所支持。 XML 处理由 xml.etree.ElementTree , xml.dom 和 xml.sax 包支持。这些模块和软件包共同大大简化了 Python 应用程序和其他工具之间的数据交换。
  • sqlite3 模块是 SQLite 数据库库的包装器,提供了一个可以使用稍微非标准的 SQL 语法更新和访问的持久数据库。
  • 国际化由许多模块支持,包括 gettext , locale ,以及 codecs 包。

11. 标准库概览 · 第二部分

11.1.输出的格式化

reprlib 模块提供了一个定制化版本的 repr() 函数,用于缩略显示大型或深层嵌套的容器对象 pprint 模块提供了更加复杂的打印控制,其输出的内置对象和用户自定义对象能够被解释器直接读取。当输出结果过长而需要折行时,“美化输出机制”会添加换行符和缩进,以更清楚地展示数据结构: textwrap 模块能够格式化文本段落,以适应给定的屏幕宽度: locale 模块处理与特定地域文化相关的数据格式。locale 模块的 format 函数包含一个 grouping 属性,可直接将数字格式化为带有组分隔符的样式:

11.2.模块

string 模块包含一个通用的 Template 类,具有适用于最终用户的简化语法。它允许用户在不更改应用逻辑的情况下定制自己的应用。

上述格式化操作是通过占位符实现的,占位符由 $ 加上合法的 Python 标识符(只能包含字母、数字和下划线)构成。一旦使用花括号将占位符括起来,就可以在后面直接跟上更多的字母和数字而无需空格分割。$$ 将被转义成单个字符 $:

1
2
3
4
from string import Template
t = Template('${village}folk send $$10 to $cause.')
t.substitute(village='Nottingham', cause='the ditch fund')
'Nottinghamfolk send $10 to the ditch fund.'

如果在字典或关键字参数中未提供某个占位符的值,那么 substitute() 方法将抛出 KeyError。对于邮件合并类型的应用,用户提供的数据有可能是不完整的,此时使用 safe_substitute() 方法更加合适 —— 如果数据缺失,它会直接将占位符原样保留。

11.3.操作二进制数据记录布局

struct 模块提供了 pack() 和 unpack() 函数,用于处理不定长度的二进制记录格式。

11.4. 多线程(之前学JAVA有点学吐了)

线程是一种对于非顺序依赖的多个任务进行解耦的技术。多线程可以提高应用的响应效率,当接收用户输入的同时,保持其他任务在后台运行。一个有关的应用场景是,将 I/O 和计算运行在两个并行的线程中。

以下代码展示了高阶的 threading 模块如何在后台运行任务,且不影响主程序的继续运行:

Copy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import threading, zipfile

class AsyncZip(threading.Thread):
    def __init__(self, infile, outfile):
        super().__init__()
        self.infile = infile
        self.outfile = outfile

    def run(self):
        with zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED) as f:
            f.write(self.infile)
        print('Finished background zip of:', self.infile)

background = AsyncZip('mydata.txt', 'myarchive.zip')
background.start()
print('The main program continues to run in foreground.')

background.join()    # 等待后台任务结束
print('Main program waited until background was done.')

多线程应用面临的主要挑战是,相互协调的多个线程之间需要共享数据或其他资源。为此,threading 模块提供了多个同步操作原语,包括线程锁、事件、条件变量和信号量。

尽管这些工具非常强大,但微小的设计错误却可以导致一些难以复现的问题。因此,实现多任务协作的首选方法是将所有对资源的请求集中到一个线程中,然后使用 queue 模块向该线程供应来自其他线程的请求。 应用程序使用 Queue 对象进行线程间通信和协调,更易于设计,更易读,更可靠。

11.5.日志记录

logging 模块提供功能齐全且灵活的日志记录系统,在最简单的情况下,日志消息被发送到文件或 sys.stderr

1
2
3
4
5
6
import logging
logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')

11.6.弱引用(这个在JAVA的GC相关部分貌似也有)

weakref 模块提供的工具可以不必创建引用就能跟踪对象。 当对象不再需要时,它将自动从一个弱引用表中被移除,并为弱引用对象触发一个回调。 典型应用包括对创建开销较大的对象进行缓存

11.7.操作列表的工具(懒得看,要用的时候自然会查)

许多对于数据结构的需求可以通过内置列表类型来满足。 但是,有时也会需要具有不同效费比的替代实现。

array 模块提供了一种 array 对象,它类似于列表,但只能存储类型一致的数据且存储密度更高。 下面的例子显示了一个由存储为双字节无符号整数的数字 (类型码 "H") 组成的元组,而不是常规 Python int 对象列表所采用的每个条目 16 字节:

1
2
3
4
5
6
from array import array
a = array('H', [4000, 10, 700, 22222])
sum(a)
26932
a[1:3]
array('H', [10, 700])

collections 模块提供了一种 deque 对象,它类似于列表,但从左端添加和弹出的速度较快而在中间查找的速度较慢。 此种对象适用于实现队列和广度优先树搜索:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from collections import deque
d = deque(["task1", "task2", "task3"])
d.append("task4")
print("Handling", d.popleft())
Handling task1
unsearched = deque([starting_node])
def breadth_first_search(unsearched):
    node = unsearched.popleft()
    for m in gen_moves(node):
        if is_goal(m):
            return m
        unsearched.append(m)

在替代的列表实现以外,标准库也提供了其他工具,例如 bisect 模块具有用于操作有序列表的函数:

1
2
3
4
5
import bisect
scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')]
bisect.insort(scores, (300, 'ruby'))
scores
[(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]

heapq 模块提供了基于常规列表来实现堆的函数。 最小值的条目总是保持在位置零。 这对于需要重复访问最小元素而不希望运行完整列表排序的应用来说非常有用:

1
2
3
4
5
6
from heapq import heapify, heappop, heappush
data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
heapify(data)                      # 将列表重新调整为堆顺序
heappush(data, -5)                 # 添加一个新条目
[heappop(data) for i in range(3)]  # 获取三个最小的条目
[-5, 0, 1]

11.8.十进制浮点算法

decimal 模块提供了一种 Decimal 数据类型用于十进制浮点运算。 相比内置的 float 二进制浮点实现,该类特别适用于 这个算有点用

  • 财务应用和其他需要精确十进制表示的用途,
  • 控制精度,
  • 控制四舍五入以满足法律或监管要求,
  • 跟踪有效小数位,或
  • 用户期望结果与手工完成的计算相匹配的应用程序。

Decimal 表示的结果会保留尾部的零,并根据具有两个有效位的被乘数自动推出四个有效位。 Decimal 可以模拟手工运算来避免当二进制浮点数无法精确表示十进制数时会导致的问题。