python高级知识点总结
线程知识
1 多任务
并行
并发
2 父线程与子线程
一个进程中默认只有一个线程 --- 主线程
3 创建子线程的两种方法
使用Thread类 实例对象
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
常用参数
target指定子线程运行的函数名
args执行子线程的函数代码在运行时 的参数
thd = threading.Thread()
使用Thread子类 实例对象
实现其中的run()方法
thd.start()方法 只是启动子线程的创建和执行
4 主线程等待子线程退出
默认情况下父线程会等待所有子线程退出
如果需要在子线程执行完成后 还需要执行一些代码(比如检测子线程+10000次之后的运算结果) 需要在主线程中使用 Thread实例对象.join()
5 同一个进程内部的多个线程 共享全局变量
6 多线程同步--秩序
互斥锁保证在任何一个时间点只有 一个 任务可以获取并占有 锁资源
创建锁资源 mutex = threading.Lock()
获取锁资源 mutex.acquire()
在默认情况下 如果锁已经被其他任务锁定 那么 本次获取将会阻塞该任务的执行
释放锁资源 mutex.release()
7 互斥锁的优缺点
优点 保证多任务修改共享数据时能够同步 使运算结果正确
缺点 1.丧失多任务优势 2.容易造成死锁问题
8 死锁问题
任务在获取锁时造成 一直在等待(死等) 锁资源 而不能成功获取
原因:
- 没有正确释放 --
- 用户规范 用完一定要关
- 权宜之计就是在获取锁的时候 使用非阻塞 或者 阻塞+超时等待 方式获取锁
- 多种锁资源分配不当 -- 银行家算法可以解决该问题
9 acquire()方法功能说明
acquire(blocking=True, timeout=-1)
函数作用 申请锁资源
参数含义 blocking参数表示是否阻塞 True表示阻塞 False表示非阻塞(不阻塞等待)
timeoute参数表示阻塞等待的最长时间 超时则放弃等待
-1表示死等
如果是一个正数 代表等待这么秒
返回值 表示是否成功获取到锁资源 True表示成功获取 False表示获取失败
acquire(True,10)
acquire(True) === acquire()
acquire(False,10)
进程
0. 进程间通信-Queue队列
创建 q = multiprocessing.Queue() 参数表示队列长度 -- 数据条数
往里面放数据q.put(data)
取出数据q.get()
判断满q.full()
判断空q.empty()
获取队列中的数据数量 mac会崩溃 q.qsize()
put(obj[, block[, timeout]])
obj表示数据对象
block表示是否阻塞等待 True表示阻塞等待 False表示不阻塞 不等待
timeout 表示如果等待 等待最长的时间
如果超时等待或者 不阻塞等待都没有获取到数据 则抛出异常
put(data,block=True,timeout=-1)
put(data,True,10)
put(data,False) 不等待 put_nowait(data)
如果超时放入 或者 非阻塞放入数据 没有完成任务 都会抛出异常
get(block=True, timeout=-1])
block表示是否阻塞等待 True表示阻塞等待 False表示不阻塞 不等待
timeout 表示如果等待 等待最长的时间 -1表示死等
get() == get(True)
get(True,10) 最多超时等待10s 如果没有取到数据 就抛出异常
get(False) 不阻塞等待 直接获取数据 如果没有取到数据 就抛出异常
1. 进程池
创建进程池 pool = Pool(进程的最大数量)
添加任务
apply是阻塞的任务添加方式 会等待添加的任务执行完成才会继续往下执行
apply_async 是非阻塞的任务添加方式 只管添加 不等任务结束
关闭进程池
.close()
pool.terminate() 终止进程池中所有的正在执行的进程任务
等待所有任务执行完成
.join() 保持主进程存活 等待所有的工作进程 全部退出
注意事项:
1. 如果需要在进程池中 使用进程间通信Queue 不要使用multiprocessing.Queue() (要求是通过继承的方式创建的进程)
应该使用 multiprocessing.Manager().Queue()
2. .join()之前 一定要调用 .close() 或者.terminate()
3. 在正常情况下 是不需要teminate()终止所有工作进程的
迭代器
1. 迭代
根据记录的前面的元素的位置信息 去访问后续的元素的过程 -遍历 迭代
2. 可迭代对象 iterable
能够被迭代访问的对象 for in
常用可迭代对象-list tuple str
from collections import Iterable
isinstance(obj, Iterable)
3. 可迭代对象
可迭代对象通过__iter__方法提供一个 可以遍历对象中数据的工具-迭代器
iter(可迭代对象) 可以获取可迭代对象的迭代器
通过迭代器可以迭代访问 数据
next(迭代器) ===== 迭代器对象.__next__()
如果需要实现一个迭代器 就需要实现__next__()
4. 迭代器 iterator -- 迭代器访问可迭代对象中数据
判断对象是否是迭代器类型
from collections import Iterator
isinstance(obj, Iterator)
自己实现
迭代器本身也是可迭代对象 __iter__() 提供迭代器(self)
下一个元素的值 = next(迭代器) =====> __next__()
5. 生成器 generator
生成器是一种特殊的迭代器 --- 是迭代器 并且有自己的特点
1 创建生成器表达式 [] ----》 (x for x in range(100))
2 生成器函数
凡是有yield关键字的函数都不是普通函数了 而是生成器函数
6. yield关键字的作用
挂起当前函数 将后面表达式的值 返回到调用生成器的地方
接收数据 并唤醒当前函数 并且紧接着上次运行的地址继续执行
7. 唤醒生成器的两种方式
生成器.send("数据")
next(生成器) === 生成器.send(None)
在第一次调用生成器对象的是 必须使用next()
在后续的情况下 send和next可以混用
协程对比 进程 线程
协程 用户层面的概念
进程 线程 都是操作系统层面的概念
正则
1. 正则表达式的使用场景
关键词-匹配
学习技巧- 理解 -多练习
<img alt="丁叮c的直播" data-original="https://rpic.douyucdn.cn/live-cover/appCovers/2017/12/27/462253_20171227014914_big.jpg" src="https://rpic.douyucdn.cn/live-cover/appCovers/2017/12/27/462253_20171227014914_big.jpg" width="283" height="163" style="display: block;">
2. 两个函数
match() 从头开始匹配 如果某个字符不能满足匹配规则 将匹配失败 返回None
直到匹配完成 将匹配结果放入匹配结果对象中
从匹配结果对象中获取到匹配结果
matchobj.group()
result = re.match(正则, 数据)
if result:
print(result.group())
else:
print("匹配失败")
search() 从头开始查找 如果某个字符不能满足匹配规则 将继续往后面查找 并尝试继续匹配
如果查找完 都没有匹配上 则返回None
如果匹配成功 将匹配结果放入匹配结果对象中
从匹配结果对象中获取到匹配结果
matchobj.group()
result = re.search(正则,数据)
if result:
print(result.group())
else:
print("匹配失败")
3. 匹配单个字符 -- 元字符
. 匹配一个任意字符(除去\n)
[] 匹配集合中任意一个字符
[-] 匹配字符范围的其中任意一个字符
[^] 禁止 集合内任意一个的字符匹配 -- 取反 黑名单
digit
\d 匹配一个任意数字字符 等价 [0123456789] == [0-9]
\D 匹配一个任意的 非数字字符 等价于 [^0123456789] == [^0-9] = [^\d]
space
\s 匹配一个任意空白字符 不止空格 等价于 [\t\r\n\v\f ]
\S 匹配一个任意的非空白字符
word
\w 匹配一个任意的 单词字符 [\da-zA-Z_]
\W 匹配一个任意的 非单词字符 [^\da-zA-Z_]
拓展-
4 匹配多个字符-量词
a. {n} 匹配前面那个字符n次
b. {n,m} 匹配 至少n次 最多m次 m可以不写 代表匹配无限次 没有上限
c. + 至少匹配一次 {1,}
d. * 任意多次 {0,}
5. 匹配位置
a. ^ 匹配开始位置
虽然match自带匹配开始的属性 但是为了正则的语义完整 建议也加上^
b. $ 匹配结束位置
匹配的是结束位置 而不是数据
6. 分组 group
目的 -- 在正则中使用() 将感兴趣的数据从整体中提取出来 放到分组存储
等整体匹配成功返回的结果对象中 .group(分组编号)就可以获取对应分组中数据了
group(0) == group() 就是正则表达式整体匹配的结果
用户的分组编号从1开始
() 表示匹配数据并放入分组
.group(分组编号)就可以获取对应分组中数据了
| 表示匹配|左边或者右边的正则表达式
(|) 表示匹配分组中| 左边或者右边的表达式 并且放入分组中
总结
1 ?在正则中出现的不同场合
(?P<name>\w??)
2 () [] {} <>在正则中的作用
HTTP
GET /grand.html HTTP/1.1
请求方式/方法 GET一般用以获取服务器的数据
POST 一般用以浏览器向服务器发送数据
用户请求路径
HTTP协议
-------后面是在请求的时候带的额外的数据
请求头---头名:值----------------
host代表请求的主机
Host: 192.168.72.76:8888
connection代表连接方式 HTTP/1.1默认就是长连接 keep-alive
Connection: keep-alive
Cache-Control: max-age=0
代表用户身份 服务器反爬 服务器根据 对不同的浏览器做适配
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36
Upgrade-Insecure-Requests: 1
代表能够接受数据的 文件类型
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
能够接受的压缩方式 ——目的:节约网络带宽 加快传输的速度
Accept-Encoding: gzip, deflate
能够接受的语言
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7
HTTP请求格式——HTTP请求报文格式
request line
请求行[请求方法 请求路径 HTTP/1.1\r\n]
请求头[请求头名称:头值\r\n]
空行[\r\n]
request body
请求体 GET请求方法一般不带请求体 POST带请求体(储存给服务器发送的文件数据或其他数据)
GET请求:
GET 路径 版本\r\n
头名:值\r\n
\r\n
POST请求:
GET 路径 版本\r\n
头名:值\r\n
\r\n
请求体
注意https和http比较
1. HTTP响应报文格式分析:
HTTP/1.1 200 OK
响应行 版本 状态码 状态说明
2xx 成功
3xx 重定向
4xx 客户端错误
5xx 服务器错误
Server: nginx/1.4.6 (Ubuntu)
代表后台服务器应用的身份
Date: Wed, 03 Jan 2018 00:56:27 GMT
Content-Type: text/html
代表数据的文件类型 浏览器根据这个类型去解析数据并且显示
Last-Modified: Tue, 04 Mar 2014 11:46:45 GMT
最后一次被修改的时间(缓存)
Connection: keep-alive
代表连接方式 长连接
Content-Encoding: gzip
代表数据采用的压缩方式 《浏览器根据这种压缩方式 进行解压缩》
2. HTTP响应报文:
响应行[版本 状态码 状态说明\r\n]
响应头[头名: 头值\r\n]
空行 [\r\n]
响应体[服务器给客户端发送的数据]