Python学习之协程
8.8 协程
我们都知道线程间的任务切换是由操作系统来控制的,而协程的出现,就是为了减少操作系统的开销,由协程来自己控制任务的切换
协程本质上就是线程。既然能够切换任务,所以线程有两个最基本的功能:一是保存状态;二是任务切换
8.8.1 协程的特点
【优点】
- 线程任务切换开销小,属于程序级的切换,操作系统感知不到
- 单线程内就可以实现并发的效果,最大限度的利用CPU
【缺点】
- 协程的本质是单线程,无法利用多核;可以一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
- 协程是单个线程执行多个任务,一旦协程遇到阻塞,将会阻塞整个线程
【特点】
- 必须要在单线程中实现并发
- 修改共享数据不需要加锁
- 用户程序内保存多个控制流的上下文栈
- 一个协程遇到IO操作自动切换到其它协程
8.8.2 Greenlet
使用grennlet第三方库实现任务间的切换
from greenlet import greenlet
def get_money(name):
print(f"{name} get 10 $")
g2.switch('jiawen')
print(f"{name} get 20 $")
g2.switch()
def buy_goods(name):
print(f"{name} buy no.1 good ")
g1.switch()
print(f"{name} buy no.2 good ")
g1.switch()
if __name__ == '__main__':
g1 = greenlet(get_money)
g2 = greenlet(buy_goods)
g1.switch('gailun') # switch在第一次时必须要传入参数,以后就不需要了
效率对比
from greenlet import greenlet
import time
def f1():
re = 1
for i in range(10000000):
re *= i
g2.switch()
def f2():
re = 1
for i in range(10000000):
re += i
g1.switch()
if __name__ == '__main__':
start = time.time()
g1 = greenlet(f1)
g2 = greenlet(f2)
g1.switch() # switch在第一次时必须要传入参数,以后就不需要了
print(f'{time.time()- start}') # 5.822627305984497
import time
def f1():
re = 1
for i in range(10000000):
re *= i
def f2():
re = 1
for i in range(10000000):
re += i
start = time.time()
f1()
f2()
print(f'{time.time()- start}') # 1.041489601135254
【结论】单纯的切换,在没有IO阻塞的情况下,协程的效率反而降低
8.8.3 Gevent介绍
Gevent也是一个第三方库,主要用来实现并发同步或是异步编程,在gevent中用到的主要模式是Greenlet, Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。
【方法】
gevent.spawn(func,*args,**kwargs) spawn括号内第一个参数是函数名,后面可以有多个参数,可以是位置实参或关键字实参,都是传给函数func,spawn是异步提交任务
join() 等待调用者结束
value() 拿到调用者的返回值
遇到IO阻塞会自动切换
import gevent
def get_money(name):
print(f"{name} get 10 $")
gevent.sleep(2) #模拟的是gevent可以识别的IO阻塞
print(f"{name} get 20 $")
def buy_goods(name):
print(f"{name} buy no.1 good ")
gevent.sleep(1)
print(f"{name} buy no.2 good ")
if __name__ == '__main__':
g1 = gevent.spawn(get_money,'gailun')
g2 = gevent.spawn(buy_goods,name='jiawen')
g1.join()
g2.join()
# gevent.joinall([g1,g2])
print('__main__')
# 输出
gailun get 10 $
jiawen buy no.1 good
jiawen buy no.2 good
gailun get 20 $
__main__
【注意】如果要使gevent识别所有的io阻塞,放到被打补丁者的前面或者直接写在在文件的最开头写上以下代码
rom gevent import monkey;monkey.patch_all()
应用
# 爬虫
from gevent import monkey;monkey.patch_all()
import gevent
import requests
import time
def get_inf(url):
print(f'GET:{url}')
res = requests.get(url)
if res.status_code == 200:
print(f"{len(res.text)} get from {url}")
if __name__ == '__main__':
start_time = time.time()
gevent.joinall(
[gevent.spawn(get_inf,'https://www.python.org/'),
gevent.spawn(get_inf,'https://www.yahoo.com/'),
gevent.spawn(get_inf,'https://github.com/'),
]
)
print(f"take {time.time()-start_time} secondes")
Python学习之协程的更多相关文章
- Python学习---线程/协程/进程学习 1220【all】
Python学习---线程基础学习 Python学习---线程锁/信号量/条件变量同步1221 Python学习---同步条件event/队列queue1223 Python学习---进程 1225 ...
- python学习笔记 协程
在学习异步IO模型前,先来了解协程 协程又叫做微线程,Coroutine 子程序或者成为函数,在所有语言中都是层级调用,比如a调用b,b调用c.c执行完毕返回,b执行完毕返回,最后a执行完毕返回 所以 ...
- python学习之-- 协程
协程(coroutine)也叫:微线程,是一种用户态的轻量级线程,就是在单线程下实现并发的效果.优点:1:无需线程上下文切换的开销.(就是函数之间来回切换)2:无需原子操作锁定及同步的开销.(如改一个 ...
- Python学习笔记--协程asyncio
协程的主要功能是单线程并发运行 假设有3个耗时不一样的任务.看看协程的效果. 先来看没有使用协程情况: #!/usr/bin/python3 # -*- coding:utf-8 -*- import ...
- [转载]Python 3.5 协程究竟是个啥
http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 协程究 ...
- [译] Python 3.5 协程究竟是个啥
转自:http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 ...
- Python基础之协程
阅读目录 一 引子 二 协程介绍 三 Greenlet模块 四 Gevent模块 引子 之前我们学习了线程.进程的概念,了解了在操作系统中 进程是资源分配的最小单位,线程是CPU调度的最小单位. 按道 ...
- python中和生成器协程相关的yield之最详最强解释,一看就懂(一)
yield是python中一个非常重要的关键词,所有迭代器都是yield实现的,学习python,如果不把这个yield的意思和用法彻底搞清楚,学习python的生成器,协程和异步io的时候,就会彻底 ...
- python基础(35):协程
1. 前言 之前我们学习了线程.进程的概念,了解了在操作系统中进程是资源分配的最小单位,线程是CPU调度的最小单位.按道理来说我们已经算是把cpu的利用率提高很多了.但是我们知道无论是创建多进程还是创 ...
随机推荐
- 第四章 生命周期函数--36 结合Node手写JSONP服务器剖析JSONP原理
- HDU - 6704 K-th occurrence (后缀数组+主席树/后缀自动机+线段树合并+倍增)
题意:给你一个长度为n的字符串和m组询问,每组询问给出l,r,k,求s[l,r]的第k次出现的左端点. 解法一: 求出后缀数组,按照排名建主席树,对于每组询问二分或倍增找出主席树上所对应的的左右端点, ...
- 处理并解决mysql8.0 caching-sha2-password问题,开启远程访问
原文:https://blog.csdn.net/u010026255/article/details/80062153 启动mysql服务:service mysqld start ALTER US ...
- JS框架_(JQuery.js)夜晚天空满天星星闪烁动画
百度云盘 传送门 密码:xftr 满天星星闪烁动画效果: (可用星空动画来作为页面背景,白色文字改为文章或者其他的O(∩_∩)O) <!doctype html> <html> ...
- linux查看端口占用情况,python探测端口使用的小程序
Linux如何查看端口 1.lsof -i:端口号 用于查看某一端口的占用情况,比如查看8000端口使用情况,lsof -i:8000 # lsof -i:8000 COMMAND PID USER ...
- Linux-expect脚本-1
expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示: 首行加上/usr/bin/expect spawn: 后面加上需要执行的shell命令,比如说spawn sudo ...
- JPA 开发写SQL时候遇见的困难点
官方文档 https://docs.spring.io/spring-data/jpa/docs/1.11.16.RELEASE/reference/html/#repositories.specia ...
- Spring Boot中使用 Thymeleaf
目录 1.pom.xml引入thymeleaf 2.关闭缓存application.properties 3.编写Controller类 4.模板html 5.运行结果 1.pom.xml引入thym ...
- 作业要求20191010-4 alpha week 1/2 Scrum立会报告+燃尽图 02
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/8747 一.小组情况组长:贺敬文组员:彭思雨 王志文 位军营 杨萍队名:胜 ...
- 后盾网lavarel视频项目---Laravel 安装代码智能提示扩展「laravel-ide-helper」
后盾网lavarel视频项目---Laravel 安装代码智能提示扩展「laravel-ide-helper」 一.总结 一句话总结: laravel-ide-helper作用是:代码提示 larav ...