python基础(下)
2020-11-15 20:23:25 0 举报
AI智能生成
登录查看完整内容
python语法基础 下
作者其他创作
大纲/内容
python基础(下)
进程
基础概念
资源分配: 分配的是cpu和内存等物理资源
进程号是进程的唯一标识
linux
ps -aux 查看进程号
ps -ef | grep 2784 过滤查找2784这个进程
kill -9 进程号 强行杀死进程
python
os.getpid() 获取当前进程号
os.getppid() 获取当前进程的父进程
同一个程序执行两次之后是两个进程
并发和并行
并发: 一个cpu同一时间不停执行多个程序
并行: 多个cpu同一时间不停执行多个程序
cpu的进程调度方法
先来先服务fcfs(first come first server): 先来的先执行
多级反馈队列算法
进程三状态
就绪(Ready)状态
执行(Running)状态
cpu开始执行该进程时称为执行状态。
阻塞(Blocked)状态
同步 异步 / 阻塞 非阻塞
场景: 在多任务当中
基本使用
基本语法
导入
from multiprocessing import Process
p = Process(target=func)
调用子进程
p.start()
带参数的进程
target=指定任务 args=参数元组
进程间数据独立
不同堆空间
进程间异步
同步子父进程: join
多进程场景
自定义进程类
必须继承Process类
必须要有run()方法
带参数
守护进程
功能
p.daemon = True
多个子进程
把死循环的进程设为守护进程
模拟: 监控报活
进程间通信
互斥锁 Lock
概念
是一种基于socket的IPC
上锁 lock.acquire() 和解锁 lock.release() 是一对
连续上锁不解锁是死锁
只有解锁状态下其他进程才有机会上锁
from multiporcessing import Lock
创建一把锁
lock = Lock()
上锁
lock.acquire()
解锁
lock.release()
模拟: 抢票程序
信号量 Semaphore
from multiporcessing import Semaphore
同一时间允许多个进程上5把锁
sem = Semaphore(5)
sem.acquire()
sem.release()
模拟: 唱歌房
事件 Event
from multiporcessing import Event
生成事件对象e
e = Event()
判断当前的属性是否为True (默认False)
print(e.is_set())
将这个属性的值改成True
e.set()
将这个属性的值改成False
e.clear()
e.wait(3)
模拟: 红绿灯
进程队列 Queue
from multiporcessing import Queue
创建进程队列
q = Queue()
(5)可以指定队列长度为5
存放
q.put()
put_nowait()
获取
print(q.get())
在获取不到数据时会发生阻塞态
get_nowait()
拿不到数据报异常
windows能用 linux不兼容
检测队列元素个数
q.qsize()
示例: 不同进程间能出队入队同一容器的数据
生产者消费者模型
生产者负责生产存储数据(put)
消费者负责使用数据(get)
比较理想的模型
生产多少消费多少
生产数据的速度和消费数据速度相对一致
示例: 通过进程队列存放和消费数据
JoinableQueue 队列
from multiporcessing import JoinableQueue
jq = JoinableQueue()
jq.put()
内置计数器属性值自动+1
jq.get()
计数器属性值-1
jq.task_done()
判断是否放行
jq.join()
示例: 优化生产者和消费者模型
Manager 数据共享
线程
线程是计算机中调度的最小单位
线程的缘起
线程的特点
python线程的缺陷
原因
全局解释器锁(Cpython解释器特有) GIL锁
想要并行的解决办法(都不治标)
用多进程间接实现线程的并行
程序分为计算密集型和io密集型
计算密集型程序会过度依赖cpu
from threading import Thread
一个进程包含多个线程
多线程间数据共享
自定义线程类
线程的相关属性
线程.is_alive()
检测线程是否仍然存在
设置查看进程名
线程.setName()
设置线程名字
线程.getName()
获取线程名字
查看进程号
currentThread().ident
查看线程id号
enumerate()
返回目前正在运行的线程列表
activeCount()
返回目前正在运行的线程数量
守护线程
t.setDaemon(True)
线程中的数据安全
互斥锁
示例: 通过计算n的值判断数据是否安全
信号量
死锁和递归锁
语法死锁
同一把锁连续acquire不释放
逻辑死锁
递归锁
用于快速解决线上项目死锁问题
用法
from threading import RLock
让noodles_lock和chopsticks_lock都等于递归锁
用法同进程的Event
模拟: 连接数据库超时
线程队列
Queue 单调队列
用法同multiprocessing.Queue
LifoQueue 栈
PriorityQueue 优先级队列
按照优先级顺序进行排序存放(默认从小到大)
进程池/线程池
优点
通过重复利用已创建的进程/线程降低创建和销毁造成的消耗
任务可以不需要等到进程/线程创建就能立即执行
提高进程/线程的可管理性
进程池
from concurrent.futures import ProcessPoolExecutor
创建进程池对象
p = ProcessPoolExecutor()
获取逻辑处理器数 os.cpu_count()
异步提交任务
获取当前任务的返回值
obj.result()
等待所有进程池里的进程执行完毕后再放行
p.shutdown()
线程池
from concurrent.futures import ThreadPoolExecutor
创建线程池对象
t = ThreadPoolExector()
其他用法同进程池
map
相当于返回值为迭代器的submit
回调函数
回头调用一下函数获取最后结果
示例: 查看回调函数的进程/线程id
线程池的回调函数由子线程执行
协程
协程是线程实现的具体方式
提高更大量的并行并发
协程版生产者消费者模型
协程版本
greenlet 早期版本
switch 手动切换任务
gevent
缺点: 不能识别所有阻塞
monkey补丁 协程终极版本
协程使用
启动协程
g1.join()
协程任务结束再放行
joinall
g1.value()
获取协程任务中的返回值
示例: 遇到阻塞自动切换协程
利用协程高效爬取数据
网络编程基础
理论基础
两大架构
C/S 架构
B/S 架构
主机标识
mac地址(物理地址)
ip 地址(逻辑地址Internet Protocol Address)
ipv4
32位的二进制数
ipv6
128位的二进制数
地址范围2^128-1
网段
作用
主要用来划分同一区域里的某些机器是否能够互相通信
依据
如果IP地址和子网掩码相与得到的值相同就是同一网段
端口
具体某个程序与外界通讯的出口
取值范围
0~65535
192.168.2.1:8000
常用端口
20 : FTP文件传输协议(默认数据口)
21 : FTP文件传输协议(控制)
22 : SSH远程登录协议
25 : SMTP服务器所开放的端口,用于发送邮件
443 : 基于TLS/SSL的网页浏览端口,能提供加密和通过安全端口传输的另一种HTTP => HTTPS
3306: MySQL开放此端口
OSI
网络七层模型
应表会传网数物
封装数据
http (超文本传输协议)
HTTPS (加密传输的超文本传输协议)
FTP (文件传输协议)
SMTP (电子邮件传输协议)
传输层
封装端口
指定传输协议 (TCP协议/UDP协议)
socket抽象层
网络层
封装ip
ipv4版本 / ipv6 (ICMP/IGMP)
数据链路层
封装mac地址
指定mac地址 (arp协议[ip->mac] / rarp协议[mac->ip])
物理层
arp协议
arp协议: 通过ip -> mac
rarp协议: 通过mac -> ip
arp协议整体是通过: 一次广播 + 一次单播 实现
TCP/UDP协议
TCP(Transmission Control Protocol)一种面向连接的、可靠的、传输层通信协议
TCP通信流程
TCP三次握手
TCP发送数据
TCP四次挥手
socket
socket模块
创建一个socket对象
SOCK_STREAM 基于TCP
SOCK_DGRAM 基于UDP
常用方法
获取要连接的对端主机地址
sk.bind(address)
将套接字绑定到地址。address地址的格式取决于地址族
sk.listen(backlog)
开始监听传入连接
backlog指定在拒绝连接之前,可以挂起的最大连接数量
sk.setblocking(bool)
是否阻塞(默认True)
如果设置False,那么accept和recv时一旦无数据,则报错。
sk.accept()
其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址
sk.connect(address)
连接到address处的套接字
sk.connect_ex(address)
同上,只不过会有返回值,连接成功返回 0,失败返回编码如:10061
sk.close()
关闭套接字
接受套接字的数据
数据以字符串形式返回
bufsize指定最多可以接收的字节数
sk.recvfrom(bufsize[.flag])
其中data是包含接收数据的字符串,address是发送数据的套接字地址
将string中的数据发送到连接的套接字
返回值是要发送的字节数量
返回值可能小于string的字节大小。即:可能未将指定内容全部发送
将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据
成功返回None,失败则抛出异常
内部通过递归调用send,将所有内容发送出去
将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址
返回值是发送的字节数
该函数主要用于UDP协议
sk.settimeout(timeout)
设置套接字操作的超时期,timeout是一个浮点数,单位是秒
sk.getpeername()
返回连接套接字的远程地址
sk.getsockname()
返回套接字自己的地址
sk.fileno()
套接字的文件描述符
一个端口绑定多个程序(仅在测试时使用)
TCP收发消息
UDP收发消息
黏包与解决
黏包现象
解决黏包
场景
解决黏包场景
不需要解决黏包场景
下载或者上传文件
方法
struck模块
pack()
unpack()
socketserver模块
注意
通过socketserver.ThreadingTCPServer() 创建server对象
通过serve_forever() 永久启动服务
加密
hashlib模块
md5算法
基本用法
创建md5对象
hs = hashlib.md5()
把要加密的数据更新到对象中
hs.update("111222".encode("utf-8"))
获取十六进制的字符串
res = hs.hexdigest()
加盐
动态加盐
使用random.randrange() 获得随机数字再编码 作为salt
使用os.urandom(字节数) 直接获得随机bytes 作为salt
sha系列
hs = hashlib.sha1() # 结果是固定长度40位的十六进制字符串
hs = hashlib.sha512("user".encode()) # 结果是固定长度128位的十六进制字符串
hmac模块
应用
加密存储密码
密钥协商
文件校验
小文件
直接使用read()比较或者hash()之后比较
也可以使用hashlib模块转为32位字符串比较
大文件
0 条评论
回复 删除
下一页