python Event事件、进程池与线程池、协程解析


Posted in Python onOctober 25, 2019

Event事件

用来控制线程的执行

出现e.wait(),就会把这个线程设置为False,就不能执行这个任务;

只要有一个线程出现e.set(),就会告诉Event对象,把有e.wait的用户全部改为True,剩余的任务就会立马去执行。由一些线程去控制另一些线程,中间通过Event。

from threading import Event
from threading import Thread
import time
# 调用Event实例化出对象
e = Event()
#
# # 若该方法出现在任务中,则为False,阻塞
# e.wait() # False
# # 若该方法出现在任务中,则将其他线程的False改为True,进入就绪态和运行态
# e.set() # True
def light():
 print('红灯亮...')
 time.sleep(5)
 # 应该发出信号,告诉其他线程准备执行
 e.set() # 将car中的False变为True
 print('绿灯亮...')
def car(name):
 print('正在等红灯...')
 # 让所有汽车任务进入阻塞态
 e.wait() # False
 print(f'{name}正在加速飘逸...')
# 让一个light线程控制多个car线程
t = Thread(target=light)
t.start()

for i in range(10):
 t = Thread(target=car, args=(f'汽车{i}号', ))
 t.start()

进程池与线程池

进程池与线程池是用来控制当前程序允许创建(进程/线程)的数量

作用:保证在硬件允许的范围内创建(进程/线程)的数量

线程池使用一:

from concurrent.futures import ThreadPoolExecutor
import time
pool = ThreadPoolExecutor(5) # 5代表只能开启5个进程, 不加默认使用cpu的进程数
# ThreadPoolExecutor(5) # 5代表只能开启5个线程
# pool.submit() #异步提交任务, 括号里传函数地址
def task():
 print('线程任务开始了...')
 time.sleep(1)
 print('线程任务结束了...')
for line in range(5):
 pool.submit(task)

使用二:

from concurrent.futures import ThreadPoolExecutor
import time

pool = ThreadPoolExecutor(5) # 5代表只能开启5个进程, 不加默认使用cpu的进程数

# ThreadPoolExecutor(5) # 5代表只能开启5个线程
# pool.submit() #异步提交任务, 括号里传函数地址
def task():
 print('线程任务开始了...')
 time.sleep(1)
 print('线程任务结束了...')
 return 123
# 回调函数
def call_back(res):
 print(type(res))
 res2 = res.result() # 注意:赋值操作不要与接收的res同名
 print(res2)
for line in range(5):
 pool.submit(task).add_done_callback(call_back)

pool.shutdown() 会让所有线程池的任务结束后,才往下执行代码

多线程爬取梨视频

利用requests模块,封装底层socket套接字

  • 主页中获取所有视频id号,拼接视频详情页url
  • 在视频详情页中获取真实视频url srcUrl=
  • 往真实视频url地址发送请求获取 视频 二进制数据
  • 最后把视频二进制数据保存到本地

协程

  • 进程: 资源单位
  • 线程: 执行单位
  • 协程: 在单线程下实现并发

注意: 协程不是操作系统资源,目的是让单线程实现并发

协程目的

  • 操作系统:使用多道技术,切换 + 保存状态,一个是遇到IO, 另一个是CPU执行时间过长
  • 协程:通过手动模拟操作系统 “多道计数”, 实现 切换 + 保存状态
    • 手动实现,遇到IO切换,欺骗操作系统误以为没有IO操作
    • 单线程时,遇到IO,就切换 + 保存状态
    • 单线程时,对于计算密集型,来回切换 + 保存状态反而效率更低

优点:在IO密集型的情况下,会提高效率

缺点:若在计算密集型的情况下,来回切换,反而效率更低

import time

def func1():
 for i in range(10000000):
  i+1

def func2():
 for i in range(10000000):
  i+1
start = time.time()
func1()
func2()
stop = time.time()
print(stop - start) # 1.0312113761901855


# 基于yield实现并发 在计算密集型的情况下效率更低

def func1():
 while True:
  10000000+1
  yield

def func2():
 g = func1()
 for i in range(10000000):
  i+1
  next(g) # 每次执行next相当于切换到func1下面
start = time.time()
func2()
stop = time.time()
print(stop - start) # 1.3294126987457275

gevent

gevent是一个第三方模块,可以帮你监听IO操作,并切换

使用gevent的目的:在单线程下实现,遇到IO就会 保存状态 + 切换

import time
from gevent import monkey

monkey.patch_all() # 可以监听该程序下所有的IO操作
from gevent import spawn, joinall # 用于做切换 + 保存状态
def func1():
 print('1')
 time.sleep(1) # IO操作
def func2():
 print('2')
 time.sleep(3)
def func3():
 print('3')
 time.sleep(5)
start = time.time()
s1 = spawn(func1)
s2 = spawn(func2)
s3 = spawn(func3)

s1.join() # 发送信号,相当于等待自己(在单线程的情况下)
s2.join()
s3.join()

# joinall((s1, s2, s3)) # 一个个执行很麻烦,可以用joinall把这些全部装进去

end = time.time()
print(end - start) # 5.006161451339722

TCP服务端socket套接字实现协程

服务端:

from gevent import monkey
from gevent import spawn
import socket

monkey.patch_all()
server = socket.socket()
server.bind(('127.0.0.1', 9999))
server.listen(5)

def task(conn):
 while True:
  try:
   data = conn.recv(1024)
   if len(data) == 0:
    break
   print(data.decode('utf-8'))
   send_data = data.upper()
   conn.send(send_data)

  except Exception:
   break
 conn.close()
def server2():
 while True:
  conn, addr = server.accept()
  print(addr)
  spawn(task, conn)
if __name__ == '__main__':
 s = spawn(server2)
 s.join()

客户端:

import socket
from threading import Thread, current_thread

def client():
 client = socket.socket()
 client.connect(('127.0.0.1', 9999))

 number = 0
 while True:
  send_data = f'{current_thread().name} {number}'
  client.send(send_data.encode('utf-8'))

  data = client.recv(1024)
  print(data.decode('utf-8'))
  number += 1


for i in range(400):
 t = Thread(target=client)
 t.start()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python flask实现分页效果
Jun 27 Python
完美解决Python 2.7不能正常使用pip install的问题
Jun 12 Python
Python对excel文档的操作方法详解
Dec 10 Python
对python pandas读取剪贴板内容的方法详解
Jan 24 Python
Python字典的基本用法实例分析【创建、增加、获取、修改、删除】
Mar 05 Python
python celery分布式任务队列的使用详解
Jul 08 Python
python  logging日志打印过程解析
Oct 22 Python
Python实现遗传算法(二进制编码)求函数最优值方式
Feb 11 Python
使用遗传算法求二元函数的最小值
Feb 11 Python
在keras 中获取张量 tensor 的维度大小实例
Jun 10 Python
python接入支付宝的实例操作
Jul 20 Python
上帝为你开了一扇窗之Tkinter常用函数详解
Jun 02 Python
python实现简单银行管理系统
Oct 25 #Python
Python银行系统实战源码
Oct 25 #Python
python实现银行管理系统
Oct 25 #Python
Django视图扩展类知识点详解
Oct 25 #Python
Python装饰器使用你可能不知道的几种姿势
Oct 25 #Python
win7下 python3.6 安装opencv 和 opencv-contrib-python解决 cv2.xfeatures2d.SIFT_create() 的问题
Oct 24 #Python
Python下应用opencv 实现人脸检测功能
Oct 24 #Python
You might like
php中用文本文件做数据库的实现方法
2008/03/27 PHP
php错误、异常处理机制(补充)
2012/05/07 PHP
Yii框架模拟组件调用注入示例
2019/11/11 PHP
JQuery优缺点分析说明
2011/04/10 Javascript
JavaScript 更严格的相等 [译]
2012/09/20 Javascript
js和jquery中循环的退出和继续学习记录
2014/09/06 Javascript
JavaScript字符串对象substring方法入门实例(用于截取字符串)
2014/10/17 Javascript
js中跨域方法原理详解
2015/07/19 Javascript
解析浏览器端的AJAX缓存机制
2016/06/21 Javascript
ExtJs异步无法向外传值和赋值的完美解决办法
2017/06/14 Javascript
解决webpack dev-server不能匹配post请求的问题
2018/08/24 Javascript
深入解析Vue源码实例挂载与编译流程实现思路详解
2019/05/05 Javascript
javascript实现的字符串转换成数组操作示例
2019/06/13 Javascript
json数据格式常见操作示例
2019/06/13 Javascript
JavaScript实现瀑布流布局的3种方式
2020/12/27 Javascript
[48:37]EG vs OG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
[44:43]完美世界DOTA2联赛决赛日 FTD vs GXR 第一场 11.08
2020/11/11 DOTA
Django的数据模型访问多对多键值的方法
2015/07/21 Python
Python守护线程用法实例
2017/06/23 Python
Python获取指定文件夹下的文件名的方法
2018/02/06 Python
关于不懂Chromedriver如何配置环境变量问题解决方法
2019/06/12 Python
Python 正则表达式 re.match/re.search/re.sub的使用解析
2019/07/22 Python
浅谈Python 函数式编程
2020/06/20 Python
python与c语言的语法有哪些不一样的
2020/09/13 Python
HTML5实现视频直播功能思路详解
2017/11/16 HTML / CSS
html5实现多文件的上传示例代码
2014/02/13 HTML / CSS
StubHub墨西哥:购买和出售您的门票
2016/09/17 全球购物
澳大利亚礼品卡商店:Gift Card Store
2019/06/24 全球购物
Hush Puppies澳大利亚官网:舒适的男女休闲和正装鞋
2019/08/24 全球购物
Douglas意大利官网:购买香水和化妆品
2020/05/27 全球购物
介绍一下gcc特性
2015/10/31 面试题
演讲稿怎么写
2014/01/07 职场文书
公司员工活动策划方案
2014/08/20 职场文书
原告代理词范文
2015/05/25 职场文书
大学生安全教育主题班会
2015/08/12 职场文书
使用这 6个Vue加载动画库来减少我们网站的跳出率
2021/05/18 Vue.js