Python笔记 #4 常用标准库和第三方库

本文最后更新于:2023年9月30日 中午

除了前面提及的的数据分析第三方库,Python 中也自带了许多有用的标准库,提供了一系列基础接口。此外本文还将介绍一些项目中常用的第三方库,更多细节可以在交互式窗口中输入 dir(xx)help(xx) 检索。

标准库

标准库通常与 Python 发行版捆绑安装,其提供的组件涉及范围十分广泛,此处仅介绍常用库。

导入标准库时建议使用 import os 风格而非 from os import *,这样在调用的时候就可以用 os.open(),避免覆盖内置的函数 open()

os 操作系统接口

Python 中与操作系统交互的标准库,可以完成目录管理、进程管理、调度器接口等操作。

在深度学习中常用于创建目录、遍历目录、操作路径。使用方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import os

# path 是字符串,可以是绝对路径,也可以是当前目录相对路径
os.mkdir(path) # 创建一级目录
os.makedirs(path) # 创建多级目录

# 先判断目标目录是否存在再新建
if not os.path.exists(path):
os.makedirs(path)

# 如果 exist_ok 为 False(默认值),则在目标目录已存在的情况下触发 FileExistsError 异常
os.makedirs(path, exist_ok=True)

# 路径相关用法 os.path
os.path.join('path','abc','1.txt') # 生成字符串 path/abc/1.txt
os.path.join('./path','abc','1.txt') # 生成字符串 ./path/abc/1.txt

os 模块还能设置环境参数,在深度学习中常用于设置 GPU 相关参数,但是必须放在 main 函数的入口处,例如:

1
2
3
4
5
if __name__ == '__main__':
# 设置 GPU
os.environ['CUDA_LAUNCH_BLOCKING'] = '1'
os.environ["TOKENIZERS_PARALLELISM"] = "false"
os.environ["CUDA_VISIBLE_DEVICES"] = '0'

此外,os 模块还能在脚本中直接使用终端命令,只需要 os.command(" ") 就能执行,常用于批量使用复杂命令。

time 时间访问和转换

Python 中处理时间的标准库,提供系统级精确计时功能(可以用于程序性能分析)。其主要功能分为三块:时间获取、时间格式化、程序计时,这里介绍计时相关内容。

  • sleep(s)s 为休眠时间,单位秒,可以是浮点数。
  • perf_counter():返回一个 CPU 级别的精确时间计数值,单位为秒。

后者的使用由于计数器起点不确定,连续调用求差值才有意义:

1
2
3
4
5
6
7
8
import time
import numpy as np

arr = np.arange(100000000)
start = time.perf_counter() # 计数器起点
arr = arr * 2
end = time.perf_counter() # 计数器终点
print('numpy time cost: %.3f s' % (end - start))

当然,如果只是想测试单条指令的用时,可以在 IPython 中调用如下命令,会多次执行计算平均值和方差

1
2
3
>>> %%timeit
>>> np.convolve(arr1, arr2)
# 4.87 s ± 3.06 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

datetime 日期与时间

Python 中用于处理日期和时间的标准库,包括三个主要的类:datetimedatetime。这些类用于表示日期、时间和日期时间。此外,还有一些函数和常量可用于日期和时间的处理。

  • date 类用于表示日期,有三个属性:yearmonthday
  • time 类用于表示时间,有三个属性:hourminutesecond
  • datetime 类用于表示日期时间,是 date 类和 time 类的组合。

下面是具体命令,使用strftime()方法将date对象格式化为字符串:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import datetime

# 创建 date 对象
d = datetime.date(2023, 4, 4)
print(d) # 2023-04-04
print(d.strftime('%Y/%m/%d')) # 2023/04/04

# 创建 time 对象
t = datetime.time(12, 30, 45)
print(t) # 12:30:45
print(t.strftime('%H:%M:%S')) # 12:30:45

# 创建 datetime 对象
dt = datetime.datetime(2023, 4, 4, 12, 30, 45)
print(dt) # 2023-04-04 12:30:45
print(dt.strftime('%Y-%m-%d %H:%M:%S')) # 2023-04-04 12:30:45

以下是一些常用的命令,可用于日期和时间的处理:

  • datetime.date.today():返回当前日期的date对象。
1
2
today = datetime.date.today()
print(today) # 2023-04-04
  • datetime.datetime.now():返回当前日期时间的datetime对象。
1
2
now = datetime.datetime.now()
print(now) # 2023-04-04 12:30:45.123
  • datetime.datetime.strptime():将字符串解析为datetime对象。需要指定字符串格式。
1
2
3
dt_str = '2023-04-04 12:30:45'
dt = datetime.datetime.strptime(dt_str, '%Y-%m-%d %H:%M:%S')
print(dt) # 2023-04-04 12:30:45
  • datetime.timedelta():用于计算时间差。
1
2
3
delta = datetime.datetime.timedelta(days=3)
new_date = today + delta
print(new_date) # 2023-04-07
  • datetime.datetime.replace():用于更改datetime对象的某些属性。
1
2
new_dt = dt.replace(hour=13, minute=0, second=0)
print(new_dt) # 2023-04-04 13:00:00
  • datetime.datetime.fromtimestamp():用于从 Unix TimeStamp 得到 datetime。
1
2
dt = datetime.datetime.fromtimestamp(ts) # 1680582645
print(dt) # 2023-04-04 12:30:45

logging 日志记录

Python 中自带的日志模块,基本使用方法如下:

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

logger = logging.getLogger(__name__) # 以当前文件名实例化 logger 记录器
logging.basicConfig(level=logging.INFO,
format='[%(asctime)s] [%(levelname)s] %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename=f'{Model_name}.log') # 简单配置日志级别与格式

# 具体用法,在代码中插入如下 message,常用 f-string
logging.debug('This is a debug message')
logging.info('This is a info message')
logging.warn('This is a warn message')
logging.error('This is a error message')
logging.critical('This is a critical message')

所谓日志级别,就是日志中只关注大于设定级别的内容:

级别何时使用
DEBUG详细信息,调试时对所有问题感兴趣
INFO事情按预期工作,训练模型最常用
WARNING可能的意外,但仍能工作
ERROR错误,软件已不能执行一些功能
CRITICAL严重错误,软件已不能继续运行

这里也可以换用暴力点的输出日志方法,直接用 Linux 的管道加 tee -a 命令,将所有输出流复制到文件中,但是这种方法不好处理 tqdm 产生的 bar。

glob 文件名模式匹配

Python 中用于查询符合特定规则的文件路径名的标准库,不用遍历整个目录判断每个文件是不是符合。使用 glob.glob('路径') 调用,返回一个符合条件的路径字符串的 List 结构,支持通配符 ***?[],具体用法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import glob

for name in glob.glob('dir/*'):
pass # * 遍历 dir 目录,但不会递归遍历子目录

for name in glob.glob('dir/*/*'):
pass # * 不会递归到子目录,因此只能手动指定

for name in glob.glob('dir/**', recursive=True):
pass # ** 遍历 dir 下所有内容,包括子目录

for name in glob.glob('dir/file?.txt'):
pass # ? 匹配任何单个的字符

for name in glob.glob('dir/*[0-9].txt'):
pass # [] 匹配指定范围内的单个字符

注意:* 通配符默认不匹配以 . 开始的文件,如 .config,如果有这类文件,则需要显式标注点号。

csv 文件读写

Python 中用来读取 CSV 文件的标准库,一个 CSV 文件经常包含若干行,每行包含若干列,列和列之前通常使用逗号分隔。其内部实现了一个 reader 类和 writer 类,用于读写序列化的数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import csv

# 读取文件,每一行是一个 List<Str>
with open('some.csv', 'r', newline='') as f:
reader = csv.reader(f)
for row in reader:
print(row)

# 写入文件,每一行是 List<Str> 或 List<List<Str>>
data = [['Name', 'Age', 'Country'],
['John', '25', 'USA'],
['Alice', '30', 'Canada'],
['Bob', '35', 'UK']]

with open('some.csv', 'a', newline='') as f:
writer = csv.writer(f)
writer.writerows(data)

# 也可以逐行写入指定数据
with open('some.csv', 'a', newline='') as f:
writer = csv.writer(f)
writer.writerow(['Name', 'Age', 'Country'])
writer.writerow(['John', '25', 'USA'])

注意:如果没有指定 newline='',则嵌入引号中的换行符将无法正确解析,并且在写入时,使用 \r\n 换行的平台会有多余的 \r 写入。由于 csv 模块会执行自己的换行符处理,因此指定 newline='' 应该总是安全的

在定义 reader 或 writer 时,可以指定以下参数:

  • delimiter=',' 每一列的分隔符,默认为逗号,但在文本字符串中更常用 \t 以避免错误分隔
  • quotechar='"' 为引号字符,默认为单引号,用于判断何时为字符串
  • escaoechar='\\' 为转义字符,默认为反斜杠,不需要修改

除此之外,本库还针对每一行为字典的 JSONL 文件定义了读写方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 每一行是一个 Dict<'Str':'Str'>,即列名和值
with open('some.csv', 'r', newline='') as f:
reader = csv.DictReader(f)
for row in reader:
print(row['Name'], row['Age'], row['Country'])

data = [{'Name':'John', 'Age':'25', 'Country':'USA'},
{'Name':'Alice', 'Age':'30', 'Country':'Canada'},
{'Name':'Bob', 'Age':'35', 'Country':'UK'}]

with open('some.csv', 'r', newline='') as f:
fieldnames = ['Name', 'Age', 'Country']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(data)

csv 库的功能大部分被 pandas 所包含,如果结构化处理数据的需求,推荐直接用 pandas 的 csv 读写函数。

argparse 命令行参数解析

Python 中用于解析命令行参数和选项的标准库。在复现较大型项目时,通常由工具脚本调用命令行参数,这些参数以链表形式存储于 sys 模块的 argv 变量,直接处理较为麻烦,因此有了该标准库。使用范例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import argparse

def read_args():
# 声明一个解析对象,以及当 -h 或参数出错时会打印的信息
parser = argparse.ArgumentParser(description="You should add those parameter!")

# 罗列所需参数,下面给出常见例子
# 通常来讲,type 和 default 是必须的,其他视情况而定
# 其中 store_true 表示默认为 False,指定时切换为 True
parser.add_argument("--path", type=str, required=True, help="The path of file")
parser.add_argument("--input_num", "-n", type=int, default=50)
parser.add_argument("--mode", type=str, choices=['train', 'test'])
parser.add_argument('--use_clip', action='store_true')


# 解析参数并返回
args = parser.parse_args()
return args

if __name__ == '__main__':
my_args = read_args()
print(my_args.path)

re 正则表达式

Python 中正则表达式匹配的标准库。模式和被搜索的字符串既可以是 Unicode 字符串(str) ,也可以是 8 位字节串(byte),但必须一致。

关于正则表达式的语法此处不过多介绍,仅给出一些示例:

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'

注意:若只需要简单的功能,应该首先考虑字符串方法,如 .replace().split() 等,更易于阅读和调试。

zipfile 文件压缩

Python 标准库中的一个模块,用于创建、读取和操作 ZIP 文件。主要作用包括:创建 ZIP 文件、解压 ZIP 文件、读取 ZIP 文件(但不进行解压)、操作 ZIP 文件(增删改)。

其中,所有的方法被封装到 zipfile.ZipFile 类,使用方法如下:

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

# 创建 zip 文件并将文件添加到其中
with zipfile.ZipFile('archive.zip', 'w') as zipf:
zipf.write('file1.txt')
zipf.write('file2.txt')

# 将 w 修改为 a,就可以向已有的文件中添加新文件
with zipfile.ZipFile('existing.zip', 'a') as zipf:
zipf.write('new_file.txt')

# 解压缩 zip 文件,参数为目标目录
with zipfile.ZipFile('archive.zip', 'r') as zipf:
zipf.extractall('extracted_dir')

对于一个已有的 ZIP 文件,可以进行的操作如下:

1
2
3
4
5
6
7
8
9
10
11
import zipfile

# 获取 zip 文件中的所有成员的名称列表
with zipfile.ZipFile('archive.zip', 'r') as zipf:
file_list = zipf.namelist()
print(zipf.getinfo('file1.txt'))

# 想要修改其中的某个文件,需要先将其解压缩,并覆盖写入
with zipfile.ZipFile('archive.zip', 'w') as zipf:
with zipf.open('file1.txt', 'r') as file:
zipf.writestr('file1.txt', file.read())

zipfile 库在实际应用中被广泛使用,特别是在需要处理大量文件或目录的情况下,使用 ZIP 文件可以方便地进行文件的打包、传输、存储和管理。

traceback 异常处理和调试

Python 中用于异常处理和调试的标准库之一。它允许查看程序执行时发生的异常信息,并追踪函数调用的堆栈。常用的函数有以下两种:

  • traceback.print_tb(tb, limit=None, file=None):打印当前异常的堆栈跟踪信息。它接受以下参数:
    • tb:表示异常信息的 traceback 对象。
    • limit:可选参数,用于指定打印堆栈跟踪信息的层数。如果不指定,将打印整个堆栈。
    • file:可选参数,用于指定输出的文件对象。如果不指定,将打印到标准输出。
  • traceback.print_exception(etype, value, tb, limit=None, file=None, chain=True):打印异常信息,包括异常类型、异常值和堆栈跟踪信息。它接受以下参数:
    • etype:异常类型。
    • value:异常值。
    • tb:表示异常信息的 traceback 对象。
    • limit:可选参数,用于指定打印堆栈跟踪信息的层数。如果不指定,将打印整个堆栈。
    • file:可选参数,用于指定输出的文件对象。如果不指定,将打印到标准输出。
    • chain:可选参数,如果为 True,将打印异常链中的所有异常信息。默认为 True
1
2
3
4
5
6
7
import traceback

try:
result = 10 / 0
except Exception as e:
traceback.print_tb(e.__traceback__)
traceback.print_exception(type(e), e, e.__traceback__)

第三方库

第三方库通常需要 pip install,建议安装在虚拟环境中,按需取用。

pipreqs 依赖安装

当我们写好一个 Python 项目之后,如果要开源代码,为了让别人能快速运行项目,一般可以提供一个 requirements.txt 的,用以配置环境。

pipreqs 是用于自动生成上述文件的一个第三方库,使用 pip install pipreqs 安装,进入项目根目录,执行 pipreqs ./ 即可。如果出现编码错误,可以指定编码方式解决:

1
pipreqs ./ --encoding utf-8

其他人则可以使用以下命令配置环境:

1
pip install -r requirements.txt

codecs 编码转换

codec 意为字符的编解码器(Encoder&Decoder),Python 对多国语言的处理是支持的很好的,它可以处理现在任意编码的字符。在作字符转换时,Python 会借助于内部的编码(Unicode),转换的过程是这样的:原有编码 -> 内部编码 -> 目的编码。而这个转换的过程就需要用到编解码器。

一种基本的用法是通过 lookup 获取特定的编码器,再用其与 Unicode 进行转换:

1
2
3
4
5
6
7
8
9
>>> import codecs
>>> codec1 = codecs.lookup("utf-8")
>>> a = "你好"
>>> b = codec1.encode(a)
>>> print(b)
(b'\xe4\xbd\xa0\xe5\xa5\xbd', 2) # 其中 2 为 len(a)
>>> c = codec1.decode(b[0])
>>> print(c)
('你好', 6) # 其中 6 为 len(b[0])

另一种更常用的用法是对文件字符编码的处理,常用于数据处理任务:

1
2
3
import codecs
# 使用 codecs 自带的 open 读取文件,指定编码方式
file = codecs.open(path, encoding='latin-1').readlines()

json 文件读写

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,但格式类似 C 系语言。易于人阅读和编写,同时也易于机器解析和生成(一般用于提升网络传输速率)。使用 pip install json-parser 安装。

Python 中的 List、Dict 最常用于 JSON 文件的转换,在此前要先将数据类型转为字符串 Str。json 模块提供了四个功能:

  • dumps:把数据类型转换成字符串
  • dump:把数据类型转换成字符串并存储在文件中
  • loads:把字符串转换成数据类型
  • load:把文件打开从字符串转换成数据类型

基本使用方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import json

test_dict = {'bigberg': [7600,
{'details': [['iPhone', 6300],
['Bike', 800],
['shirt', 300]]
}]
}
json_str = json.dumps(test_dict) # dict -> str
new_dict = json.loads(json_str) # str -> dict

with open("../config/record.json","w") as f:
json.dump(new_dict,f) # dict -> str -> json

with open("../config/record.json",'r') as load_f:
load_dict = json.load(load_f) # json -> str -> dict

注意:JSON 文件通常是不可读的,因为其将整个列表或字典压缩到同一行字符串中,以减少文件体积。如果要增加其可读性,可以在转换时指定缩进,例如 dump(data, file, indent=4)

注意:JSON 保存输出时默认会将非 ASCII 字符进行 Unicode 转移,生成 \u...,如果想要禁止这一过程,可以在 dump 中使用 ensure_ascii=False。该设置不会影响 load 方法。

此外,还有一种 JSONL 文件,一行为一条记录或数据(可读性稍好),常用作日志文件数据集,支持用 json 操作:

1
2
3
4
5
6
7
8
9
10
data = []
with open("input.jsonl",'r') as f:
data_in = f.readlines() # jsonl -> list[str]
for obj in data_in:
data.append(json.loads(obj)) # list[str] -> list[dict]

with open("output.jsonl","w") as f:
for obj in data:
f.write(json.dumps(obj) + '\n') # list[dict] -> list[str] -> jsonl
# 这里的 \n 不可缺少,因为 write 不会自动换行

常见错误:在使用 dump 的时候报错 TypeError: Object of type int64 is not JSON serializable,这是由于 dump 不能处理 NumPy 中的数据类型,此时需要手动给整数套上 int()、浮点数套上 float()、多维数组加上 .tolist()。也可以通过重加载 JSONEncoder 实现上述功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import json
import numpy as np

class NpEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.integer):
return int(obj)
if isinstance(obj, np.floating):
return float(obj)
if isinstance(obj, np.ndarray):
return obj.tolist()
return super(NpEncoder, self).default(obj)

json.dumps(data, cls=NpEncoder)

jsonlines 文件读写

当然,上述操作也可以使用专门的 JSONL 处理模块替代:

1
2
3
4
5
6
7
8
9
10
import jsonlines

data = []
with jsonlines.open('input.jsonl', encoding='utf-8') as reader:
for obj in reader: # 隐含 jsonl -> str -> dict
data.append(obj) # -> list[dict]

with jsonlines.open('output.jsonl', mode='w', encoding='utf-8') as writer:
for obj in data: # -> dict
writer.write(obj) # 隐含 dict -> str -> jsonl,自动换行

tqdm 进度条

tqdm 是一个用于在 Python 命令行中添加进度条的库。它提供了一种简单而有效的方式来监测长时间运行的任务的进度,只需用 tqdm(iterable) 装饰任何可迭代对象,就能直观地看到进度条:

1
2
3
4
5
import time
from tqdm import tqdm # 新手常常犯错的点:直接 import tqdm

for i in tqdm(range(1000)): # tqdm 返回值本身也是一个可迭代对象
time.sleep(0.1) # 模拟耗时操作

此时命令行输出的样式如下:

1
35%|██████████                          | 35/100 [00:02<00:05, 18.78it/s]

tqdm() 中传入参数可以修改样式:

  • bar_format="{l_bar}{bar}| {n_fmt}/{total_fmt}" 设置进度条样式
  • ncols=80 设置进度条总长度,默认为填充整行命令行
  • desc="Processing" 设置前缀,默认为空,即只显示百分比
  • postfix={"loss": 0, "acc": 0} 设置额外的后缀项目
  • leave=True 进度条在完成后是否保持可见,默认为 True

实际上 tqdm() 除了可以直接传入可迭代对象,也可以使用 with 语句来创建了一个 tqdm 的上下文管理器。通过设置 total 参数为迭代对象的长度来告诉 tqdm 进度条的总长度,并使用 update() 来在每轮迭代中更新。

1
2
3
4
5
6
# 创建上下文管理器,更优雅,不需要 pbar.close()
with tqdm(total=len(train_loader)) as pbar:
for item, label in train_loader:
pbar.set_description(f"Processing...") # 等同于 desc
pbar.set_postfix(loss=loss, acc=acc) # 等同于 postfix
pbar.update() # 手动增加进度条的当前值,默认 +1

那么如何优雅地在深度学习训练框架中应用 tqdm 呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
for epoch in range(num_epochs):
losses = []
num_correct = 0
with tqdm(total=len(train_loader), ncols=20) as pbar:
for idx, (inputs, targets) in enumerate(train_loader):
optimizer.zero_grad()
inputs, targets = inputs.to(device), targets.to(device)
preds = model(inputs)
loss = criterion(preds, targets)

losses.append(loss)
loss.backward()
optimizer.step()

num_correct += (predictions == targets).sum()
acc = num_correct / (idx + 1) * batch_size

pbar.set_description(f'Epoch [{epoch}/{num_epochs}]')
pbar.set_postfix(loss=round(loss.item(),4), acc=round(acc,4))
pbar.update()

pprint 美化输出

全称 Pretty Print,用于替代原来的 print() 函数,主要用于打印复杂的数据结构对象,例如多层嵌套的列表、元组和字典等。常用于多层嵌套的内容(例如复杂的 json 文件),或者有超多的元素(例如在列表中存了很多 URL 链接)。功能有:

  • 设置合适的行宽度,作适当的换行;
  • 设置打印的缩进、层级,进行格式化打印;
  • 判断对象中是否有无限循环,并优化打印内容。

基本使用方法如下:

1
2
3
from pprint import pprint
# 完整接口:pprint(object, stream=None, indent=1, width=80, depth=None, compact=False)
pprint(json.loads(sample_file[0]))

PIL 图像处理

全称 Python Imaging Library,有时也称 pillow,使用 pip install pillow 安装。支持众多图像格式,可用于执行裁剪、大小调整、旋转、滤镜效果等操作,引入时通常使用 from PIL import Image

基本使用方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
from PIL import Image

# 打开、显示、保存,以及图像的三个属性:模式(RGB,L)、大小(像素)、格式
image = Image.open('input.jpg')
image.show()
image.save('output.jpg')
print(image.mode, image.size, image.format) # RGB (481, 321) JPEG

grey_image = image.convert('L') # 从 RGB 转为 L 灰度图像
grey_image.show()

r, g, b = image.split() # 彩色图像可以分离出 R、G、B 通道,每个通道都是一个图像
im = Image.merge('RGB', (b, g, r)) # 按照一定的顺序再合并成彩色图像

支持对图像整体、局部进行像素级操作:

1
2
3
4
5
6
7
8
9
10
11
12
box = (100, 100, 300, 300)  # 设置一个四元组裁剪框
region = image.crop(box) # 减除
region = region.transpose(Image.ROTATE_180) # 旋转 180 度
image.paste(region, box) # 粘贴

im = image.resize((300, 300)) # 使用插值算法缩放
im = image.rotate(45) # 逆时针旋转 45 度
im = image.transpose(Image.FLIP_LEFT_RIGHT) # 左右翻转
im = image.transpose(Image.FLIP_TOP_BOTTOM) # 上下翻转

im = image.point(lambda i: i * 1.2) # 对每个像素值乘以 1.2
im = image.point(lambda i: i > 128 and 255) # 二值化,利用 and 短路

还支持与 Numpy 的交互,用于手动实现图像处理算法:

1
2
3
array = np.array(image)
print(array.shape) #(321, 481, 3)
i = Image.fromarray(array)

注意,PIL 只能完成基础的图像处理,更高端的操作还得用到 OpenCV 的 cv2 模块,例如:仿射变换、基本绘制、随机变化等。

Jupyter Notebook

Jupyter Notebook 有两种键盘输入模式:

  1. 编辑模式,允许你往单元中键入代码或文本;这时的单元框线是绿色的。
  2. 命令模式,键盘输入运行程序命令;这时的单元框线是灰色。

命令模式(按键 Esc 开启)快捷键

  1. Enter:转入编辑模式
  2. Ctrl-Enter:运行本单元
  3. Shift-Enter:运行本单元,选中下个单元
  4. Alt-Enter:运行本单元,在其下插入新单元
  5. Y:单元转入代码状态
  6. M:单元转入 Markdown 状态
  7. 方向键:选中上方、下方单元
  8. A:在上方插入新单元
  9. B:在下方插入新单元
  10. X:剪切选中的单元
  11. C:复制选中的单元
  12. Shift-V:粘贴到上方单元
  13. V:粘贴到下方单元
  14. Z:恢复删除的最后一个单元
  15. Shift-M:合并选中的单元

编辑模式(Enter 键启动)下快捷键

  1. Tab:代码补全或缩进
  2. Shift-Tab:提示
  3. Esc:进入命令模式
  4. Ctrl-Enter:运行本单元
  5. Shift-Enter:运行本单元,选中下一单元
  6. Alt-Enter:运行本单元,在下面插入一单元

Python笔记 #4 常用标准库和第三方库
https://hwcoder.top/Python-Note-4
作者
Wei He
发布于
2022年4月13日
许可协议