协程(coroutine)
也叫:微线程,是一种用户态的轻量级线程,就是在单线程下实现并发的效果。
优点:
1:无需线程上下文切换的开销。(就是函数之间来回切换)
2:无需原子操作锁定及同步的开销。(如改一个变量就相当于一个原子操作,因为协程是在单线程内操作,属于串行,所以不需要锁的操作)
3:方便切换控制流,简化编程模型。
4:高并发+高扩展+低成本:一个CPU支持上万个协程都不是问题,所以很适合用于高并发处理。(因为它都在一个线程里处理)
缺点:
1:无法利用多核资源,协程的本质是个单线程,它不能同时将单个CPU上的多个核用上,协程需要和进程配合才能运行在多CPU上,一般用于CPU密集型
2:进行阻塞操作会阻塞掉整个程序
gevent (实现自动切换):是一个第三方库,可以通过gevent实现并发同步或异步编程,其中的主要模式是Greenlet,
greenlet (实现手动切换)由gevent进行了封装

举例:通过手动切换实现协程

 import gevent
def fun1():
print('输出函数1')
gevent.sleep(2)
print('函数1结束')
def fun2():
print('输出函数2')
gevent.sleep(1)
print('函数2结束')
def fun3():
print('输出函数3')
gevent.sleep(0)
print('函数3结束')
gevent.joinall([gevent.spawn(fun1),gevent.spawn(fun2),gevent.spawn(fun3)])生成3个函数的自动切换

以上代码解释:对3个函数生成自动切换,先运行fun1函数,遇到sleep(2)是,执行等待2秒,然后直接切换到fun2函数,执行遇到sleep(1)时,执行
等待1秒,继续切换到fun3函数,执行遇到sleep(0)时切换到fun1函数,发现sleep(2)未完成,又切换入fun2函数发现sleep(1)也没有执行完成,
继续切换如fun3函数,这里sleep(0)不用等待,直接执行fun3的最后一个print,执行完成后,返回fun1函数的sleep,发现没有完成,又切入
fun2函数,发现sleep(1)已完成,可以向下继续执行,执行完下面的语句后,最后返回fun1,这时fun1的sleep(2)已完成,继续执行fun1剩下的语句。

举例:使用普通串行爬网页与使用协程的gevent进行爬网页对比用时

import gevent,time
from gevent import monkey
from urllib import request
monkey.patch_all() # gevent补丁,把当前的所有的IO操作都单独的坐上标记 def web(url):
print('开始爬网页%s' % url)
res = request.urlopen(url)
data = res.read()
print('%d bytes received from %s' % (len(data),url))
urls = [
'https://web1/',
'https://web2/',
'https://web3/'
]
# 串行模式执行
time_start = time.time()
for url in urls:
web(url)
print('同步cost',time.time()-time_start)
# 协程并发模式执行
async_time_start = time.time()
gevent.joinall([
gevent.spawn(web,'https://web1/'),
gevent.spawn(web,'https://web2/'),
gevent.spawn(web,'https://web3/')
])
print('异步cost',time.time()-async_time_start)

举例:通过协程实现一个socket服务器端(客户端没啥变化不写了)

 import sys,socket,time,gevent
from gevent import socket,monkey
monkey.patch_all() def server():
s = socket.socket()
s.bind(('0.0.0.0',9999))
s.listen(500)
while True:
cli,addr = s.accept()
# 主要这里,将每个连进来的客户端对象交给协程并发处理
gevent.spawn(handle_request,cli) def handle_request(client):
while True:
try:
data = client.recv(1024).decode()
print(data)
client.send(data.encode('utf-8'))
if not data:
client.shutdown(socket.SHUT_WR)
except Exception as e:
print('err',e)
finally:
client.close()

python学习之-- 协程的更多相关文章

  1. Python学习---线程/协程/进程学习 1220【all】

    Python学习---线程基础学习 Python学习---线程锁/信号量/条件变量同步1221 Python学习---同步条件event/队列queue1223 Python学习---进程 1225 ...

  2. python学习笔记 协程

    在学习异步IO模型前,先来了解协程 协程又叫做微线程,Coroutine 子程序或者成为函数,在所有语言中都是层级调用,比如a调用b,b调用c.c执行完毕返回,b执行完毕返回,最后a执行完毕返回 所以 ...

  3. Python学习之协程

    8.8 协程 ​ 我们都知道线程间的任务切换是由操作系统来控制的,而协程的出现,就是为了减少操作系统的开销,由协程来自己控制任务的切换 ​ 协程本质上就是线程.既然能够切换任务,所以线程有两个最基本的 ...

  4. Python学习笔记--协程asyncio

    协程的主要功能是单线程并发运行 假设有3个耗时不一样的任务.看看协程的效果. 先来看没有使用协程情况: #!/usr/bin/python3 # -*- coding:utf-8 -*- import ...

  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 协程究 ...

  6. [译] Python 3.5 协程究竟是个啥

    转自:http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 ...

  7. Python基础之协程

    阅读目录 一 引子 二 协程介绍 三 Greenlet模块 四 Gevent模块 引子 之前我们学习了线程.进程的概念,了解了在操作系统中 进程是资源分配的最小单位,线程是CPU调度的最小单位. 按道 ...

  8. python中和生成器协程相关的yield之最详最强解释,一看就懂(一)

    yield是python中一个非常重要的关键词,所有迭代器都是yield实现的,学习python,如果不把这个yield的意思和用法彻底搞清楚,学习python的生成器,协程和异步io的时候,就会彻底 ...

  9. python基础(35):协程

    1. 前言 之前我们学习了线程.进程的概念,了解了在操作系统中进程是资源分配的最小单位,线程是CPU调度的最小单位.按道理来说我们已经算是把cpu的利用率提高很多了.但是我们知道无论是创建多进程还是创 ...

随机推荐

  1. 解决Ueditor在bootstarp 模态框中全屏问题

    基本的一些配置就不说了.先说一下要注意的问题:首先是zIndex的设置.记住最好都显示设置模态框和ueditor的zIndex.理清他们的层叠关系. 特别是用到ueditor里面的图片上传功能的更要设 ...

  2. 如何使用capedit分割数据包文件

    wireshark是一个网络数据包的分析工具,主要用来捕获网卡上的数据包并显示数据包的详细内容.在处理一些大的数据包文件时,如果直接用wireshark图形工具打开一些大文件的数据包会出现响应慢甚至没 ...

  3. OpenJudge_2757:最长上升子序列

    描述一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的.对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列(ai1 ...

  4. docker存储管理

    Docker 镜像的元数据 repository元数据 repository在本地的持久化文件存放于/var/lib/docker/image/overlay2/repositories.json中 ...

  5. Caused by: java.lang.IllegalArgumentException: Parameter Maps collection does not contain value for com.bj186.crm.pojo.User

    原因分析: myBatis在写delete语句的时候,多写了一个属性 错误的代码: <delete id="deleteUser" parameterType="I ...

  6. ES6 第三章 变量的解构赋值 具体参照http://es6.ruanyifeng.com

    1.基本用法 let [a, b, c] = [1, 2, 3];左右两边解构格式要保持一致. 2.默认值 let [x, y = 'b'] = ['a']; // x='a', y='b' let ...

  7. HTML中pre标签的用法

    我们经常会在要保持文本格式的时候使用pre标签,比如当我们要展示源代码的时候,只要放一个pre标签,然后把源代码直接复制,粘贴,然后在页面上就可以保持好格式.不会像放在其它标签里那样,把换行和空格都自 ...

  8. eclipse修改SVN账号密码

    首先,eclipse中打开window------>preferences------->SVN页面,如下所示: 注意我圈起来的地方,JavaHL是不可用的,因此SVN接口应该是SVNKi ...

  9. FileZilla Server安装配置教程

    1. FileZilla官网下载FileZilla Server服务器,目前最新版本为0.9.53. 2. 安装FileZilla服务器.除以下声明的地方外,其它均采用默认模式,如安装路径等. 2.1 ...

  10. SqlSugar直接执行Sql

    参考:http://www.codeisbug.com/Doc/8/1132 我的思路: 1.数据库中写好sql 2.用SqlSugar直接执行sql,获取DataTable的数据 3.DataTab ...