网络、进程间通信

asyncio

协程与任务

  • 协程包含两层概念

    • 协程函数:定义形式为async def的函数
    • 协程对象:调用协程函数返回的对象
  • 可等待对象:可在await语句种使用的对象

    • 协程对象
    • asyncio.Future:异步调用结果的占位符
      • 以便通过async/await使用基于回调的代码
      • 通过情况下无需在应用层级代码中显式创建Future 对象
    • asyncio.TaskFuture子类,包装coroutine的future
  • 运行协程(对象)的三种方式

    • await阻塞式等待协程执行完毕
      • 只能在async def函数中使用
      • await同样是在事件循环中阻塞执行
    • 将协程对象包装为可并发运行的asyncio.Task,并在事件 循环中并发执行
      • asyncio.create_task
    • asyncio.run()创建、管理事件循环的高层API
      • 启动事件循环执行是真正运行协程对象的开始

asyncio.run

1
def asyncio.run(coro, *, debug=False);
  • 功能:创建新的事件循环并在结束时关闭

    • 执行传入的协程,并返回结果
    • 管理asyncio事件循环、终结异步生成器、关闭线程池
  • 应当被用作asyncio程序的主入口点,理想情况下只被调用一次

  • 同一线程中只能有一个asyncio事件循环运行,若同线程中有 其他事件循环运行,此函数不能被调用

Task

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class asyncio.Task(Future):
def __init__(coro,*,loop=None,name=None);
# 1、此方法仅在下轮事件循环中`raise asyncio.CancelledError`
# 给被封包协程,协程自行选择是否取消
# 2、协程等待的`Future`对象同样会被取消
def cancel(msg=None);
bool cancelled();
bool done();
def result();
def exception();
def add_done_callback(callback, *, context=None);
def remove_done_callback(callback);
def get_stack(*, limit=None);
def print_stack(*, limit=None, file=None);
def get_coro();
def get_name();
def set_name(value);
  • Task:用于在事件循环中运行协程,非线程安全
    • 若协程在等待Future对象,Task对象会挂起该协程执行 并等待该Future对象完成再执行
    • 事件循环使用协同日程调度,事件循环每次运行一个Task 对象,Task对象会等待Future对象完成,事件循环会 运行其他Task、回调、执行IO操作
    • 不建议手动实例化Task对象,可以使用高层级的 asyncio.create_task(),或低层级的 loop.create_task()ensure_future()创建
  • asyncio.TaskFuture继承了除Future.set_result()Future.set_exception()外的所有API

create_task

1
def asyncio.create_task(coro, *, name=None);
  • 功能:将协程打包为task,排入日程准备执行

  • 任务会在get_running_loop()返回的循环中执行

    • 若线程中没有在运行的循环则引发RuntimeError
  • python3.7加入,之前版本可以使用asyncio.ensure_future()

gather

1
awaitable asyncio.gather(*aws, return_exception=False)
  • 功能:并发运行aws序列中的可等待对象

    • aws中的某个可等待对象为协程对象,则会自动作为 任务加入日程
    • 若所有等待对象都成功完成,结果将是所有返回值列表, 结果顺序同aws中对象顺序
    • gather被取消,被提交的可等待对象也被取消
    • aws中task、future被取消,将被当作引发 CancelledError处理,gather也不会被取消
  • 参数说明

    • return_exception
      • False:首个异常被传播给等待gather()的任务
      • True:异常和成功结果一样处理并被聚合至结果列表

shield

1
awaitable asyncio.shield(aw);
  • 功能:保护可等待对象防止其被取消

    • aw是协程,则将自动作为任务加入日程
    • 包含shield的协程被取消,aw中的任务不会被取消, 但若aw的调用者被取消,await表达式仍然会 raise CancelledError
    • 若通过其他方式取消aw,则shield也会被取消
  • 希望完全忽略取消操作则需要配合try/except

    1
    2
    3
    4
    try:
    res = await shield(aw)
    except CancelledError:
    res = None

其他

  • Task内省

    1
    2
    3
    4
     # 返回当前运行Task实例,没有则返回`None`
    Task = asyncio.current_task(loop=None)
    # 返回`loop`事件循环未完成Task对象
    Set(Task) = asyncio.current_task(loop=None)
  • Sleep

    1
    coroutine asyncio.sleep(delay, result=None, *, loop=None)

等待超时

wait_for

1
coroutine asyncio.wait_for(aw, timeout);
  • 功能:等待aw可等待对象完成
    • 发生超时则取消任务并raise asyncio.TimeoutError
    • 函数会等待直到aw实际被取消,则总等待时间可能会超过 timeout
    • 可以通过shield避免任务被取消
    • 若等待被取消,则aw也被取消

wait

1
2
(done, pending) asyncio.wait(aws, *, timeout=None,
return_when=ALL_COMPELTED);
  • 功能:并发运行aws并阻塞线程直到满足return_when指定 的条件

    • 超时不会raise asyncio.TimeoutError,而会在返回未 完成的FutureTask
  • 参数

    • return_when
      • FIRST_COMPLETED:任意可等待对象结束、取消时 返回
      • ALL_COMPLETED:所有可等待对象结束、取消时返回
      • FIRST_EXCEPTION:任意可等待对象引发异常结束时 返回,否则同ALL_COMPLETED

as_completed

1
iterator asyncio.as_completed(aws, timeout=None);
  • 功能:并发运行aws中可等待对象,返回协程迭代器,返回的 每个协程可被等待以从剩余可等待对象集合中获得最早下个结果
    • 超时则raise asyncio.TimeoutError
1
2
for coro in asyncio.as_completed(aws):
earliest_result = await coro

其他线程中执行

to_thread

1
coroutine asyncio.to_thread(func, *args, **kwargs);
  • 功能:在不同线程中异步运行函数func
    • argskwargs会被直接传给func
    • 当前contextvars.Context被传播,允许在不同线程中 访问来自事件循环的上下文变量
    • 主要用于执行可能会阻塞事件循环的函数
      • 对于CPython实现,由于GIL存在,此函数一般只能将 IO密集型函数变为非阻塞
      • 对于会释放GIL的扩展模块、无此限制的替代性python 实现,此函数也可以被用于CPU密集型函数

run_coroutine_threadsafe

1
concurrent.futures.Future asyncio.run_coroutine_threadsafe(coro, loop)
  • 功能:向事件循环loop提交协程coro
    • 线程安全
    • 此函数应该从另一个系统线程中调用

socket

ssl

select

selectors

asyncore

asynchat

signal

mmap

Python语言服务

parser

ast

symtable

token

keyword

tokenize

tabnanny

pyclbr

py_compile

compileall

dis

dis.dis

1
2
def dis.dis(func)
# 打印可拆解函数语句对应机器指令
  • 将多条语句包装为函数,方便查看对应指令

pickletools

国际化

locale

1
2
3
4
import locale

locale.getpreferredencoding()
# 获取平台默认编码方案

gettext

文件、目录访问

pathlib

os.path

判断存在

1
2
3
4
5
os.path.isdir(r"C:\Users")
os.path.isfile(r"C:\Users")
# 判断路径名是简单文件、目录
os.path.exists(r"C:\Users")
# 判断路径名是否存在
  • os.stat配合stat模块有更丰富的功能

路径操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
pfile = os.path.join(r"C:\temp", "output.txt")
# 连接文件名、目录

os.path.split(pfile)
# 分离文件名、目录

os.path.dirname(pfile)
# 返回路径中目录
os.path.basename(pfile)
# 返回路径中
os.path.splitext(pfile)
# 返回文件扩展名

os.path.normpath(r"C:\temp/index.html")
# 调整路径为当前平台标准,尤其是分隔符混用时
os.path.abspath("index.html")
# 返回文件的**完整绝对路径名**
# 扩展`.`、`..`等语法
  • os.sep配合字符串.join.split方法可以实现基本相同 效果

fileinput

stat

stat:包含os.stat信息相关常量、函数以便跨平台使用

1
2
3
4
5
6
7
8
import stat

info = os.stat(filename)
info[stat.ST_MODE]
# `stat.ST_MODE`就是字符串
# 只是这样封装易于跨平台
stat.S_ISDIR(info.st_mode)
# 通过整数`info.st_mode`判断是否是目录
  • os.path中包含常用部分相同功能函数

glob

glob.glob

1
2
3
import glob

def glob.glob(pathname,*,recursive=False)
  • 参数

    • pathname:文件名模式
      • 接受shell常用文件名模式语法
        • ?:单个字符
        • *:任意字符
        • []:字符选集
      • .开头路径不被以上?*匹配
    • recursive
      • False:默认
      • True**将递归匹配所有子目录、文件
  • 返回值:匹配文件名列表

    • 目录前缀层次同参数
  • glob.glob是利用glob.fnmatch模块匹配名称模式

shutil

shutil模块:包含文件操作相关

fnmatch

linecache

macpath

filecmp

tempfile

通用操作系统服务

os

os:与Python所在底层操作系统相对应变量、函数

  • os模块提供了POSIX工具

    • 操作系统调用的跨平台移至标准
    • 不依赖平台的目录处理工具
      • os.path
  • 包含在C程序、shell脚本中经常用到的所有操作系统调用,涉及 目录、进程、shell变量

  • 实践中,os基本可以作为计算机系统调用的可移植接口 使用

    • 只要技术上可行,os模块都能跨平台
    • 但在某些平台,os提供专属该平台的工具

Shell变量

1
2
3
4
5
os.environ
# 获取、设置shell环境变量,类似字典
os.putenv()
# 修改进程对应shell环境变量
os.getenv()

os.environ

os.environ可以向普通字典一样键索引、赋值

  • 默认继承系统所有环境变量、命令行临时环境变量

  • 在最新的python中,对os.environ的键值修改将自动导出 到应用的其他部分

    • os.environ对象
    • 进程对应shell环境变量:通过后台调用os.putenv生效, 反之不会更新os.environ
  • python进程、链入C模块、该进程派生子进程都可以获取新的 赋值

    • 子进程一般会继承父进程的环境变量设定
    • 可以作为传递信息的方式

os.putenv

  • os.putenv同时会调用C库中的putenv(若在系统中可用) 导出设置到python链接的C库

    • 底层C库没有putenv则可将os.environ作为参数传递

管理工具

1
2
3
4
5
6
os.getpid()
# 调用函数的进程id
os.getcwd()
# 当前工作目录CWD
os.chdir(r"C:\Users")
# 更改当前工作目录CWD

移植工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
os.sep
# python底层运行平台采用的**目录组**分隔符号
# linux: `/`、win:`\`、某些mac:`:`
os.pathsep
# 目录列表(字符串形式)中分隔目录的字符
# posix机:`:`、win:`;`
os.curdir
# 当前目录代表
# linux:`.`
os.pardir
# 父目录代表
# linux:`..`
os.linesep
# 换行符
# linux:`\n`

||Linux|Win|Unix| |———|——————|———|———| |sep|/|\|/(某些MAC:)| |pathsep|:|;|| |curdir|.||| |pardir|..||| |linesep|\n|\r\n||

  • 借助这些变量可以系统相关字符串操作的跨平台
  • win下目录组分隔符是\,大部分情况下看到\\是作为\ 转义字符,防止\和之后字符转义
    • 确认不会转义时,直接使用\也是可以的
    • 使用r''表示不转义也可以直接使用\

目录、文件操作

1
2
3
4
5
6
7
8
9
10
11
12
os.mkdir(dirname)
os.rename(ori_name, dest_name)
os.remove(filename)
os.unlink(filename)
# unix下文件删除,同`os.remove`
os.chmod(filename, previlideges)
info = os.stat(filename)
# 命名元组表示的文件底层信息
# 可使用`stat`模块处理、解释信息
os.listdir(dirpath)
os.walk(rootdir, topdown=True/False)
# 遍历根目录下的整个目录树

os.listdir

  • 返回值:包含目录中所有条目名称的列表

    • 名称不带目录路径前缀
  • 需要注意的是:文件名同样有编码

    • 若参数为字节串,返回文件名列表也是字节串
    • 参数为字符串,返回文件名列表也是字符串
    • open函数也可以类似使用字节串确定需要打开的文件
    • glob.globos.walk内部都是通过调用os.listdir 实现,行为相同
  • glob模块也有遍历目录的能力

os.walk

  • 返回值:返回迭代器

    • 每个元素为(dirname, subdirs, subfile)
  • 参数

    • topdown:默认True,自顶向下返回

文件描述符、文件锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
descriptor = os.open(path, flags, mode)
# 打开文件并返回底层描述符
os.read(descriptor, N)
# 最多读取N个字节,返回一个字节串
os.write(descriptor, string)
# 将字节串写入文件
os.lseek(descriptor, position, how)
# 移动文件游标位置
descriptor.flush()
# 强制刷出缓冲

new_fd = os.dup(fd)
# 创建文件描述符副本
os.dup2(fd_src, fd_dest)
# 将文件描述符`fd_src`复制至`fd_dest`
  • os通过调用文件的描述符来处理文件

  • 基于文件描述符的文件以字节流形式处理

    • 没有字符解码、编码、换行符转换
    • 除了缓冲等额外性能,基于描述符的文件和二进制文件模式 对象类似
  • 文件流对象、工具仅仅是在基于描述符的文件的封装

    • 可以通过.fileno()获得文件流对象对应文件描述符, sys.stdinsys.stdoutsys.stderr对应文件 描述符是:0、1、2

      1
      2
      os.write(1, b"hello world\n")
      sys.stdout.write("hello world\n")
    • 可以通过os.fdopen把文件描述符封装进文件流对象

      1
      2
      3
      fdfile = os.open("filename", (os.O_RDWR|os.O_BINARY))
      filstream = os.fdopen(fdfile, "r", encoding="utf-8",
      closefd=False)

os.open

1
2
3
4
5
def os.open(path,
flags,
mode=511, *,
dir_fd=None
)
  • 参数

    • mode:需要模式标识符进行二进制操作以得到需要的模式

      • os.O_RDWR
      • os.O_RDONLY
      • os.O_WRONLY
      • os.O_BINARY
      • os.O_EXCL:唯一访问权,是python在并发、进程 同步情况下锁定文件最便捷的方法
      • os.O_NONBLOCK:非阻塞访问
      • 其他模式选项参见os模块
  • 返回值:文件描述符

    • 整数代码、句柄,代表操作系统的中文件

退出进程

1
2
os._exit(0)
# 调用进程立即退出,不输出流缓冲、不运行清理处理器

io

time

argparse

argparse:编写用户友好的命令行接口

argparse.ArgumentParser

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
class argparse.ArgumentParser:
def __init__(self,
prog=None, # 程序名,可用`$(prog)s`引用
usage=None, # 用法字符串
description=None, # 程序描述
epilog=None, # 程序尾描述
parents=[], # 父解析器,共用当前参数
formatter_class=argparse.HelpFormatter,
prefix_chars="-"/str, # 参数前缀(可包含多个可选)
fromfile_prefix_chars=None, # 指定其后参数为存储参数文件名
argument_default=None,
conflict_handler="error"/"resolve" # 默认不允许相同选项字符串
# 有不同行为,可设置为
# "resolve"表示允许覆盖
add_help=True, # 符解释器中应禁止
allow_abbrev=True, # 允许前缀匹配(若不存在重复前缀)
):
pass

# 打印、输出信息至标准输出
def print_usage(self, file=None/IO) -> None:
pass
def print_help(self, file=None/IO) -> None:
pass
def format_usage(self) -> str:
pass
def format_help(self) -> str:
pass

# 退出
def exit(self, exit=0, message=None):
pass
def error(self, message):
pass

添加参数

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
 # 添加参数
def add_argument(self,
?*name_or_flag=*[str], # 选项名(无前缀表示位置参数)
action="store"/"store_const"/ # 参数动作
"store_true"/"store_false"/
"append"/"append_const"/
"count"/"help"/"version",
nargs=None/int/"?"/"*"/"+"
const=None, # `action`、`nargs`所需常数
default=None, # 未指定参数默认值
type=str/type, # 参数被转换类型、内建函数
choices=None, # 参数类型
required=None, # 选项候选集
help=None, # 选项描述
metavar=None, # 参数值示例
dest=None, # `parse_args()`返回的参数属性名
):
pass

# 添加参数组,参数选项将可以注册至此
def add_argument_group(self,
title=None,
description=None
) -> argparse._ArgumentGroup:
pass

# 添加互斥参数组,互斥组内仅有一个参数可用
def add_mutally_exclusive_group(self,
rquired=False # 互斥组中至少有一个参数
) -> argparse._MutaullyExclusiveGroup:
pass

# 设置默认值,优先级高于选项中默认值
def set_defaults(self,
**kwargs: {参数属性名: 默认值}
):
pass

# 获取默认值
def get_default(self,
**kwargs: {参数属性名: 默认值}
):
pass
  • 参数
    • action:关联命令行参数、动作,除以下预定义行为, 还可以传递argparse.Action子类、相同接口类
      • store:存储值,默认行为
      • store_const:存储const指定值,通常用于在 选项中指定标志
      • store_true/"store_false":类上
      • append:存储列表,适合多次使用选项
      • append_const:将const参数值追加至列表, 适合多个选项需要在同一列表中存储常数 (即多个dest参数相同)
      • count:计算选项出现次数
      • help:打印完整帮助信息
      • version:打印version参数值
-    `nargs`:参数消耗数目,指定后`pare_args`返回列表,
    否则参数消耗由`action`决定

    -    `int`:消耗参数数目,`nargs=1`产生单元素列表,
        和默认不同
    -    `?/*/+`:类似普通正则,`+`会在没有至少一个参数时
        报错
    -    `argparse.REMAINDER`:所有剩余参数,适合用于从
        命令行传递参数至另一命令行

-    `const`:保存不从命令行读取、被各种动作需求的常数
    -    `action="store_const"/"append_const"`:必须给出
    -    `nargs=?`:气候选项没有参数时,使用`const`替代

-    `type`:允许任何类型检查、类型转换,一般内建类型、
    函数可以直接使用
    -    `argparse.FiltType("w")`:为文件读写方便,预定义
        类型转换

-    `dest`:`parse_args()`返回的参数属性名
    -    位置选项:缺省为首个选项名
    -    关键字选项:优秀首个`--`开头长选项名,选项目中间
        `-`被替换为`_`

参数解析

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
 # 解析参数,无法解析则报错
def parse_args(self,
args=None/list, # 需要解析参数列表,默认`sys.argv`
namespace=None # 存放属性的`Namespace`对象,缺省创建新空对象
) -> argparse.Namespace:
pass

# 解析部分参数,无法解析则返回
def parse_known_args(self,
args=None/list,
namespace=None
) -> (argparse.Namespace, [ ]):
pass

# 允许混合位置参数、关键字参数
def parse_intermixed_args(self,
args=None,
namespace=None
) -> argparse.Namespace:
pass
def parse_known_intermixed_args(self,
args=None,
namespace=None
) -> argparse.Namespace:
pass
  • 说明
    • 仅不包含类似负数的选项名,参数才会被尝试解释为负数 位置参数
    • 前缀无歧义时,可以前缀匹配

添加子命令

1
2
3
4
5
6
7
8
9
10
11
12
13
def add_subparsers(self,
title,
description,
prog,
parser_class,
action,
option_string,
dest,
required,
help,
metavar
):
pass

辅助类

动作类

1
2
3
4
5
6
class argparse.Action:
def __init__(self, option_string, dest, nargs=None, **kwargs):
pass

def __call__(self, parser, namespace, values, option_string=None):
pass

格式化类

1
2
3
4
5
6
7
class argparse.ArgumentDefaultHelpFormatter
# 认为两程序描述已被正确格式化,保留原样输出
class argparse.RawDescriptionHelpFormatter
# 保留所有种类文字的空格,包括参数描述
class argparse.RawTextHelpFormatter
# 为每个参数使用`type`参数名作为其显示名,而不是`dest`
class argparse.MetavarTypeHelpFormatter

其他类

1
2
3
4
5
6
7
8
9
10
11
12
 # 容纳属性的类
class argparse.Namespace:
pass
# IO接口简化类
class argparse.FileType:
def __init__(self,
mode="r"/"w",
bufsize=-1,
encoding=None,
errors=None
):
pass

getopt

optparse

logging

logging.config

logging.handlers

getpass

curses

curses.textpad

curses.ascii

curses.panel

platform

errno

ctypes

文件打包

zlib

gzip

bz2

lzma

zipfile

tarfile

Python并行

threding

_thread

_dummy_thread

dummy_threading

multiprocessing

concurrent

concurrent.futures

subprocess

sched

queue

数字、数学

numbers

math

cmath

decimal

fractions

random

statics

文本处理服务

string

re

difflib

textwrap

unicodedata

stringrep

readline

rlcompleter

内置异常

基类

具体警告

警告

异常层次服务