day27-迭代器协议,协程,同步异步
day27
总结
review
""" !./env python -*- coding: utf-8 -*- @Time: 2021/6/3 9:21 @Author: 三玖天下第一 @File: review.py @Software: PyCharm回顾知识点 """""" 创建线程的三种方式:1. 创建Thread对象 ---> target / args ---> start()2. 继承Thread类 ---> 重写run()方法 ---> start()3. 使用线程池(最佳选择)---> 减少频繁创建和释放线程造成的系统开销线程间的通信非常简单,可以通过共享内存来实现 进程间的通信比较麻烦,因为进程间的内存是相互隔离的,需要使用管道、套接字等方式来通信多进程 ---> 计算密集型任务 ---> 科学计算 / 音视频编解码 / 加密算法多线程 异步I/O ---> I/O密集型任务 ---> Web应用 / 爬虫 / 数据读写什么时候会使用多线程???~ 任务耗费的时间比较长(会造成其他任务的阻塞)~ 任务之间没有偏序关系(一个任务不用等另一个任务执行完毕)多线程程序的好处?~ 提升执行效率~ 改善用户体验 """""" I/O操作模式:同步:调用一个函数,必须等函数返回以后代码才能往下执行- 阻塞:- 非阻塞:异步:调用一个函数,不必等函数返回代码就可以往下执行- 阻塞: ---> 多路I/O复用- 非阻塞: ---> 回调式I/OjAVA ---> bto ----> NTO ---> AIOPython做并发(并行)编程的三种方式:~ 多线程~ 多进程~ 异步编程/异步IO ---> 协作式迭代器:实现了迭代器协议的对象 迭代器协议对应两个魔术方法:__iter__、__next__~ __iter__: 获取迭代器对象~ __next__: 获取到下一个值妈妈让我去厨房烧一锅水,准备下饺子 阻塞:水只要没烧开,我就干瞪眼看着这个锅,沧海桑田,日新月异,我自岿然不动,厨房就是我的家,烧水是我的宿命。非阻塞:我先去我屋子里打把王者,但是每过一分钟,我都要去厨房瞅一眼,生怕时间长了,水烧干了就坏了,这样导致我游戏也心思打,果不然,又掉段了。同步:不管是每分钟过来看一眼锅,还是寸步不离的一直看着锅,只要我不去看,我就不知道水烧好没有,浪费时间啊,一寸光阴一寸金,这锅必须发我13薪异步:我在淘宝买了一个电水壶,只要水开了,它就发出响声,嗨呀,可以安心打王者喽,打完可以吃饺子喽~总结: 阻塞/非阻塞:我在等你干活的时候我在干啥? 阻塞:啥也不干,死等 非阻塞:可以干别的,但也要时不时问问你的进度 同步/异步:你干完了,怎么让我知道呢? 同步:我只要不问,你就不告诉我 异步:你干完了,直接喊我过来就行"""""" 作业:写一个可以迭代出从2开始的若干个质数(只能被1和自身整除的正整数) """from threading import Thread from multiprocessing import Process, freeze_supportdef run_task():while True:passif __name__ == '__main__':freeze_support()for _ in range(5):p = Process(target=run_task)p.start()p.terminate() # 结束进程for _ in range(5):t = Thread(target=run_task)t.start()
守护线程
""" !./env python -*- coding: utf-8 -*- @Time: 2021/6/3 10:00 @Author: 三玖天下第一 @File: example02.py @Software: PyCharm守护线程 - 不值得 主线程结束,子线程结束 """ import time from concurrent.futures import ThreadPoolExecutor from threading import Threaddef output(content):while True:print(content, end='')time.sleep(0.01)if __name__ == '__main__':Thread(target=output, args=('Ping',), daemon=True).start()Thread(target=output, args=('Pong',), daemon=True).start()# 子线程中有一个没停主线程就没停,所以只要有一个不是守护线程,所有的子线程都不会停# Thread(target=output, args=('Pong',), daemon=False).start()# thread_pool = ThreadPoolExecutor(max_workers=20)# for _ in range(10):# thread_pool.submit(output, 'Pong')# thread_pool.shutdown(wait=True)
锁
""" !./env python -*- coding: utf-8 -*- @Time: 2021/6/3 10:11 @Author: 三玖天下第一 @File: example03.py @Software: PyCharm定义一个类描述一个银行账户(余额为0,存钱,取钱) 创建一个银行账户对象,启动100个线程,每个线程向该用户转1元 转账完成后查看银行账户余额。注意:存钱和取钱的受理需要耗费时间当多个线程竞争一个资源的时候,如果资源本身并不是线程安全的,会出现问题 如果代码中需要对数据进行保护(保护临界资源),需要对数据加锁如果对象实现了上下文管理协议,就可以用到with语法中 上下文管理器就是两个魔术方法:- __enter__(self): 加锁_ __exit__(self): 释放锁 """ import time from threading import Thread, RLockclass BankAccount:def __init__(self, name):self.name = nameself.id = '139485682642873'self.balance = 1000# 重入锁(一般情况下我们使用的锁都是重入锁)self.lock = RLock()def save_money(self, money):"""存钱# 如果多个现场同时执行这行代码,那么后面的线程对余额的更新会覆盖前面的更新# 这个现象在数据库层面有可能发生,我们叫丢失更新(第一类丢失更新和第二类丢失更新):param money: 需要存钱金额:return: None"""# 获得锁with self.lock:new_balance = money + self.balancetime.sleep(0.01)self.balance = new_balancedef get_balance(self):return self.balancedef draw_money(self, money):"""取钱"""if money <= self.balance:with self.lock:new_balance = self.balance - moneytime.sleep(0.02)self.balance = new_balancereturn moneyreturn 0if __name__ == '__main__':account = BankAccount('小玖')thread_list = []for _ in range(100):t = Thread(target=account.save_money, args=(1, ))t.start()thread_list.append(t)# for _ in range(60):# t = Thread(target=account.draw_money, args=(1,))# t.start()# thread_list.append(t)for thread in thread_list:thread.join()print(f'余额:{account.get_balance()}')
线程池
""" !./env python -*- coding: utf-8 -*- @Time: 2021/6/3 11:26 @Author: 三玖天下第一 @File: example04.py @Software: PyCharm创建和释放一个线程都会产生比较大的开销,所以程序要长时间的使用多个线程 最好的方式是通过线程池来使用线程 基本上不需要创建和释放线程,程序和线程池之间是借还关系池化技术是一种典型的空间换时间的技术 """import time from concurrent.futures import ThreadPoolExecutor from multiprocessing.queues import Queue from queue import Queue from threading import RLockclass BankAccount:def __init__(self, name):self.name = nameself.id = '139485682642873'self.balance = 1000# 重入锁(一般情况下我们使用的锁都是重入锁)self.lock = RLock()def save_money(self, money):"""存钱# 如果多个现场同时执行这行代码,那么后面的线程对余额的更新会覆盖前面的更新# 这个现象在数据库层面有可能发生,我们叫丢失更新(第一类丢失更新和第二类丢失更新):param money: 需要存钱金额:return: None"""# 获得锁with self.lock:new_balance = money + self.balancetime.sleep(0.01)self.balance = new_balancedef get_balance(self):return self.balancedef draw_money(self, money):"""取钱"""if money <= self.balance:with self.lock:new_balance = self.balance - moneytime.sleep(0.02)self.balance = new_balancereturn moneyreturn 0if __name__ == '__main__':account = BankAccount('小玖')print(account.balance)# pool = ThreadPoolExecutor(max_workers=64)# for _ in range(100):# res = pool.submit(account.save_money, 1)# pool.shutdown()with ThreadPoolExecutor(max_workers=256) as pool:for _ in range(1000):pool.submit(account.save_money, 1)print(account.balance)
迭代器协议
""" !./env python -*- coding: utf-8 -*- @Time: 2021/6/3 14:46 @Author: 三玖天下第一 @File: example06.py @Software: PyCharm """ import requests import timeclass FibIter:def __init__(self, num):self.a, self.b = 0, 1self.num = numself.counter = 0def __iter__(self):return selfdef __next__(self):if self.counter < self.num:self.a, self.b = self.b, self.a+self.bself.counter += 1return self.araise StopIteration()if __name__ == '__main__':fiter = FibIter(20000)for x in fiter:print(x)
协程
""" !./env python -*- coding: utf-8 -*- @Time: 2021/6/3 15:08 @Author: 三玖天下第一 @File: example08.py @Software: PyCharm """ import time""" 协程(coroutine): 互相协作的子程序(两个函数) 生成器经过预激活操作就可以升级为一个协程yield ---> 产出 / 让步 """def func():sum1 = 1for x in range(10):sum1 *= xtime.sleep(0.1)return sum1def calc_avg():total, counter = 0, 0avg_value = Nonewhile True:curr_num = yield avg_valuetotal += curr_numcounter += 1avg_value = total / counterdef main():gen = calc_avg()print(type(gen)) # <class 'generator'># 将生成器预激活 ---> 携程# next(gen)print(gen.send(None))for _ in range(5):num = int(input())print(gen.send(num))if __name__ == '__main__':main()
异步
""" !./env python -*- coding: utf-8 -*- @Time: 2021/6/3 16:09 @Author: 三玖天下第一 @File: example9.py @Software: PyCharm使用异步函数来创建协程对象 async ---> asynchronous sync ---> synchronous """# 调用该函数不是执行函数体而是得到一个协程对象 # 协程对象需要挂载到一个事件循环上才能运转起来 import asyncioasync def say_hello():print('hello, world')if __name__ == '__main__':loop = asyncio.get_event_loop()loop.run_until_complete(say_hello())loop.close()
""" !./env python -*- coding: utf-8 -*- @Time: 2021/6/3 16:20 @Author: 三玖天下第一 @File: example10.py @Software: PyCharm同步 ---> 有序, 异步 ---> 无序 异步非阻塞式调用 ---> 写作式并发 ---> 多个子线程相互协作提高效率 """ import time import asynciodef display(num):print(num)time.sleep(1)async def asy_display(num):print(num)hhe = await asyncio.sleep(1)print(hhe)await asyncio.sleep(3)# asyncio.sleep(1)def main():for num in range(9):display(num)def main2():cos = [asy_display(num) for num in range(9)]loop = asyncio.get_event_loop()# asyncio.wait(cos) ===># await cos[0]# await cos[1]# await cos[2]# ...loop.run_until_complete(asyncio.wait(cos))# cos = asy_display(10)# loop = asyncio.get_event_loop()# loop.run_until_complete(cos)async def main3():await asy_display(10)if __name__ == '__main__':# main()# main2()loop = asyncio.get_event_loop()loop.run_until_complete(main3())loop.close()
作业
质数迭代器
class PrimeNumber:def __init__(self, num):self.digit = 2self.counter = 0self.num = numdef __iter__(self):return selfdef __next__(self):if self.counter < self.num:if self.counter == 0 and self.digit == 2:self.counter += 1return self.digitwhile True:self.digit += 1for x in range(2, int(self.digit**0.5)+1):if self.digit % x == 0:breakelse:self.counter += 1return self.digitraise StopIteration()if __name__ == '__main__':prime_num = PrimeNumber(10000)for x in prime_num:print(x)
aiohttp爬取网页
import aiohttp import asyncio from bs4 import BeautifulSoupasync def analysis(html):soup = BeautifulSoup(html, 'lxml')return soup.select_one('head > title').get_text()async def main(url, analysis, save_func):headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3861.400 QQBrowser/10.7.4313.400"}html = await get_html(url, headers=headers)content = await analysis(html)await save_func(content)async def get_html(url, *, headers={}, params={}, proxy=''):async with aiohttp.ClientSession() as session:async with session.get(url, headers=headers, params=params, proxy=proxy) as response:return await response.text()async def post_html(url, *, headers={}, data={}, proxy=''):async with aiohttp.ClientSession() as session:async with session.post(url, headers=headers, data=data, proxy=proxy) as response:return await response.text()async def save(data):print(data)if __name__ == '__main__':loop = asyncio.get_event_loop()urls = ['http://python.org', 'https://www.baidu.com', 'https://www.jd.com','https://now.qq.com/pcweb/topic.html', 'https://mini.yyrtv.com','https://www.runoob.com/python3/python3-tutorial.html', 'https://www.52pojie.cn/thread-389591-1-1.html','https://ext.dcloud.net.cn/plugin?id=148', 'http://www.rjkflm.com/andtest', 'https://www.iconfont.cn/']cos = [main(url, analysis, save) for url in urls]loop.run_until_complete(asyncio.wait(cos))
day27-迭代器协议,协程,同步异步相关推荐
- python3异步协程爬虫_Python实现基于协程的异步爬虫
Python实现基于协程的异步爬虫 一.课程介绍 1. 课程来源 本课程核心部分来自<500 lines or less>项目,作者是来自 MongoDB 的工程师 A. Jesse Ji ...
- python异步爬虫_Python实现基于协程的异步爬虫
Python实现基于协程的异步爬虫 一.课程介绍 1. 课程来源 本课程核心部分来自<500 lines or less>项目,作者是来自 MongoDB 的工程师 A. Jesse Ji ...
- python协程和异步编程
文章目录 协程 & 异步编程(asyncio) 1. 协程的实现 1.1 greenlet 1.2 yield 1.3 asyncio 1.4 async & awit 1.5 小结 ...
- python 协程和异步的关系_python协程与异步协程
在前面几个博客中我们一一对应解决了消费者消费的速度跟不上生产者,浪费我们大量的时间去等待的问题,在这里,针对业务逻辑比较耗时间的问题,我们还有除了多进程之外更优的解决方式,那就是协程和异步协程.在引入 ...
- python3异步编程_协程 Python异步编程(asyncio)
协程(Coroutine) 也可以被称为微线程,是一种用户态内的上下文切换技术.简而言之,其实就是通过一个线程实现代码块相互切换执行. 直接上代码,例如: 同步编程 import time def f ...
- Python 彻底解读协程与异步【看完包会】
title: Python 协程与异步 copyright: true top: 0 date: 2018-08-11 10:15:50 tags: categories: Python进阶笔记 pe ...
- 使用单线程,多线程,协程,异步爬取包图网大国工匠视频
使用单线程爬取,多线程,协程爬取,异步爬取包图网视频 文章目录 使用单线程爬取,多线程,协程爬取,异步爬取包图网视频 第一步使用单线程爬取包图网视频 多线程爬取视频 用协程爬取 基于协程的异步爬取 第 ...
- Day10-Python3基础-协程、异步IO、redis缓存、rabbitMQ队列
内容目录: Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko S ...
- Unity中迭代器和协程的部分概念
协程本质上也是一个迭代器,为了记录一下今天对二者的学习和巩固记录一下今天的知识点. 首先了解一下迭代器的知识: 迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露 ...
- Go 学习笔记(25)— 并发(04)[有缓冲/无缓冲通道、WaitGroup 协程同步、select 多路监听通道、close 关闭通道、channel 传参或作为结构体成员]
1. 无缓冲的通道 无缓冲的通道(unbuffered channel)是指在接收前没有能力保存任何值的通道. 这种类型的通道要求发送 goroutine 和接收 goroutine 同时准备好,才能 ...
最新文章
- thonny中文版(python编辑器)
- java 登录牵手_Java: HttpURLConnection 模拟登录方法 (带cookie 的Post/Get)_20160908_七侠镇莫尛貝...
- 缓存击穿/穿透/雪崩
- linux资源使用统计指南,指南:工作量分析文档
- 2013江苏计算机二级vfp试题,2013年3月全国计算机二级VFP真题
- 笨方法“学习python笔记之文件操作
- 智慧园区主要功能及典型案例分析
- AI 智能会议系统(36)---AI 书单
- mfc-PlaySound
- 电商价格战 谁才是最大受益者
- 内存映射和独立存贮器
- CIM即时通讯源码初步解析(一款个人推荐的带集群的开源项目)
- mysql 字段扩容_关于数据库扩容与缩容
- ls、du命令的用法
- 教育心理学有一句名言
- 【深度学习笔记1.1】人工神经网络(内含模型保存与恢复介绍)
- 第三方账号登陆-sina微博_PC篇
- Ubuntu 根目录结构
- 重新配置Tomcat
- 特斯拉服务器位置,特斯拉云服务器
热门文章
- 第三章:IP地址加掩码讲解和ping命令运用
- HDFS命令:hdfs dfs
- 2022年计算机考研408考点清单(1.0版本已更完——欢迎指正)
- C++ vector内存分配机制
- 内存碎片产生原因及处理
- 轻松解决 “Error creating bean with name 'indentDao' defined in file”的错误(一)
- 使用Canvas绘制调色板和工艺卡片
- 0x5003eaed指令引用的0x00000000内存。该内存不能为read
- 思科:利用三层交换机实现vlan间路由
- Vue -- vue-router(路由)的基本使用