携程的意义:
计算型的 *** 作,利用协程来回切换执行,没有任何意义,来回切换并保存状态 反倒会降低性能。
IO型的 *** 作,利用协程在IO等待时间就去切换执行其他任务,当IO *** 作结束后再自动回调,那么就会大大节省资源并提供性能,从而实现异步编程(不等待任务结束就可以去执行其他代码)
2. 协程和多线程之间的共同点和区别:共同点:
都是并发 *** 作,多线程同一时间点只能有一个线程在执行,协程同一时间点只能有一个任务在执行;
不同点:
多线程,是在I/O阻塞时通过切换线程来达到并发的效果,在什么情况下做线程切换是由 *** 作系统来决定的,开发者不用 *** 心,但会造成竞争条件 (race condition) ;
协程,只有一个线程,在I/O阻塞时通过在线程内切换任务来达到并发的效果,在什么情况下做任务切换是开发者决定的,不会有竞争条件 (race condition) 的情况;多线程的线程切换比协程的任务切换开销更大;
对于开发者而言,多线程并发的代码比协程并发的更容易书写。
一般情况下协程并发的处理效率比多线程并发更高。
3. greenlet实现协程greenlet用于创建协程,switch用于进行协程之间的切换某个协程在执行的过程中可以随时的被其他协程通过switch函数来打断,转而去执行其他协程,当前协程的中断现场会被保留,一旦中断的协程再次获得cpu的执行权首先会恢复现场然后从中断处继续执行这种机制下的协程是同步,不能并发
pip install greenlet
import timeimport greenletdef func1(): print("func11") gr2.switch() time.sleep(1) print("func22") gr2.switch()def func2(): print("func33") gr1.switch() time.sleep(1) print("func44")start = time.time()gr1 = greenlet.greenlet(func1)gr2 = greenlet.greenlet(func2)gr1.switch()end = time.time()print(end - start)
4. yIEld关键字实现协程def func1(): yIEld 1 yIEld from func2() yIEld 3def func2(): yIEld 2 yIEld 4ff = func1()for item in ff: print(item)
5. (1)gevent实现协程pip install gevent
from greenlet import greenletfrom time import sleepdef func1(): print("协程1") sleep(2) g2.switch() print("协程1恢复运行")def func2(): print("协程2") sleep(1) g3.switch()def func3(): print("协程3") sleep(1) g1.switch()if __name__ == '__main__': # 使用greenlet来创建三个协程 g1 = greenlet(func1) g2 = greenlet(func2) g3 = greenlet(func3) # print(g1) g1.switch() # 让协程g1取抢占cpu资源
(2) gevent实现异步协程# 协程被创建出来以后默认是多个协程同步执行# 我们可以加入monkey补丁,把同步的协程转成异步协程from gevent import monkey # 注意:monkey的引入必须在其他模块之前monkey.patch_all() # 用monkey给整个协程队列,添加一个非阻塞I/O的补丁,使得他们成为异步协程import timeimport requestsimport geventheaders = { 'User-Agent': 'Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}def func(url, i): print("协程%d开启!" % i) res = requests.get(url=url, headers=headers) HTML = res.text print("协程%d执行结束,获取到的响应体大小为:%d" % (i, len(HTML)))if __name__ == '__main__': start = time.time() urls = [ "https://www.baIDu.com/", "https://www.qq.com/", "https://www.sina.com.cn", "https://www.ifeng.com/", "https://www.163.com/" ] # 创建5个协程分别对上面5个网站进行访问 g_List = [] for i in range(len(urls)): g = gevent.spawn(func, urls[i], i) g_List.append(g) # func(urls[i], i) gevent.joinall(g_List) end = time.time() print(end - start)
5. asyncio模块实现异步协程在python3.4及之后的版本使用,asyncio厉害之处在于:遇到IO *** 作时会自动切换执行其它任务
import timeimport asyncio@asyncio.coroutinedef func1(): print(1) yIEld from asyncio.sleep(1) # 遇到IO耗时 *** 作,自动切换到tasks中的其它任务 print(2)@asyncio.coroutinedef func2(): print(3) yIEld from asyncio.sleep(1) # 遇到IO耗时 *** 作,自动切换到tasks中的其它任务 print(4)tasks = [ asyncio.ensure_future(func1()), asyncio.ensure_future(func2())]start = time.time()loop = asyncio.get_event_loop()loop.run_until_complete(asyncio.wait(tasks))end = time.time()print(end - start
6. 未完待续...
总结:
在程序中只要看到async
和await
关键字,其内部就是基于协程实现的异步编程,这种异步编程是通过一个线程在IO等待时间去执行其他任务,从而实现并发。
如果是 I/O 密集型,且 I/O 请求比较耗时的话,使用协程。
如果是 I/O 密集型,且 I/O 请求比较快的话,使用多线程。
如果是 计算 密集型,考虑可以使用多核 cpu,使用多进程。
以上是内存溢出为你收集整理的python中asyncio异步编程全部内容,希望文章能够帮你解决python中asyncio异步编程所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)