在操作系统中进程是资源分配的最小单位, 线程是CPU调度的最小单位。

协程:是单线程下的并发,又称微线程,纤程。英文名Coroutine。一句话说明:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。也就是说程序员用代码来控制切换.

参考: http://www.cnblogs.com/Eva-J/articles/8324673.html

# 进程 启动多个进程 进程之间是由操作系统负责调用
# 线程 启动多个线程 真正被CPU执行的最小单位实际是线程
# 开启一个线程 创建一个线程 寄存器 堆栈
# 关闭一个线程 # 协程
# 本质上是一个线程
# 能够在多个任务之间切换来节省一些IO时间
# 协程中任务之间的切换也消耗时间,但是开销要远远小于进程线程之间的切换
# 实现并发的手段 import time
def consumer():
while True:
x = yield
time.sleep(1)
print('处理数据 :',x) def producer():
c = consumer()
next(c)
for i in range(10):
time.sleep(1)
print('生产数据:',i)
c.send(i) # 这个生产者消费者模型 模拟了程序的来回切换, 但是不能规避IO时间
producer()

使用pip3 install greenlet 和 pip3 install gevent 安装好模块,继续:

# 真正的协程模块就是使用greenlet完成的切换
from greenlet import greenlet def eat():
print('eating start')
g2.switch() # 切换到g2
print('eating end')
g2.switch() def play():
print('playing start')
g1.switch() # 切换到g1
print('playing end') g1 = greenlet(eat) # 委托给g1
g2 = greenlet(play)
g1.switch()
  • greenlet可以实现协程,不过每一次都要人为的去指向下一个该执行的协程,显得太过麻烦。python还有一个比greenlet更强大的并且能够自动切换任务的模块gevent

参考:https://www.cnblogs.com/PrettyTom/p/6628569.html

# 协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。
import time
import gevent def eat():
print('eating start')
# time.sleep(1) # gevent 不能感知到time.sleep时间
gevent.sleep(1)
print('eating end') def play():
print('playing start')
gevent.sleep(1)
print('playing end') g1 = gevent.spawn(eat)
g2 = gevent.spawn(play)
g1.join()
g2.join()

gevent的正确方式:

## 导入这句,将所有模块中的阻塞IO都打成一个包。就可以感知 time.sleep
from gevent import monkey;monkey.patch_all()
import time
import gevent
import threading def eat():
print(threading.current_thread().getName()) # Dummy 假的,虚拟的。
print(threading.current_thread())
print('eating start')
time.sleep(1.2)
print('eating end') def play():
print(threading.current_thread().getName())
print(threading.current_thread())
print('playing start')
time.sleep(1)
print('playing end') g1 = gevent.spawn(eat) # 注册到协程,遇到IO将自动切换
g2 = gevent.spawn(play)
# g1.join()
# g2.join()
gevent.joinall([g1,g2])
print('master')
# 进程和线程的任务切换由操作系统完成
# 协程任务之间的切换由程序(代码)完成,只有遇到协程模块能识别的IO操作的时候,程序才会进行任务切换,实现并发的效果

同步和异步:

# 同步 和 异步
from gevent import monkey;monkey.patch_all()
import time
import gevent def task(n):
time.sleep(1)
print(n) def sync():
for i in range(5):
task(i) def async():
g_lst = []
for i in range(5):
g = gevent.spawn(task,i)
g_lst.append(g)
gevent.joinall(g_lst) # for g in g_lst:g.join() sync() # 同步
async() # 异步

爬虫时使用协程并发

# 协程 : 能够在一个线程中实现并发效果的概念
# 能够规避一些任务中的IO操作
# 在任务的执行过程中,检测到IO就切换到其他任务 # 多线程 被弱化了
# 协程 在一个线程上 提高CPU 的利用率
# 协程相比于多线程的优势 切换的效率更快 # 爬虫的例子
# 请求过程中的IO等待
from gevent import monkey;monkey.patch_all()
import gevent
from urllib.request import urlopen # 内置的模块 def get_url(url):
response = urlopen(url)
content = response.read().decode('utf-8')
return len(content) g1 = gevent.spawn(get_url,'http://www.baidu.com')
g2 = gevent.spawn(get_url,'http://www.sogou.com')
g3 = gevent.spawn(get_url,'http://www.taobao.com')
g4 = gevent.spawn(get_url,'http://www.hao123.com')
g5 = gevent.spawn(get_url,'http://www.cnblogs.com')
gevent.joinall([g1,g2,g3,g4,g5])
print(g1.value)
print(g2.value)
print(g3.value)
print(g4.value)
print(g5.value) ret = get_url('http://www.baidu.com')
print(ret)

python并发_协程的更多相关文章

  1. python 并发编程 协程 目录

    python 并发编程 协程 协程介绍 python 并发编程 协程 greenlet模块 python 并发编程 协程 gevent模块 python 并发编程 基于gevent模块实现并发的套接字 ...

  2. python并发编程&协程

    0x01 前导 如何基于单线程来实现并发? 即只用一个主线程(可利用的cpu只有一个)情况下实现并发: 并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操 ...

  3. python 并发编程 协程 gevent模块

    一 gevent模块 gevent应用场景: 单线程下,多个任务,io密集型程序 安装 pip3 install gevent Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步 ...

  4. Python之路【第十七篇】:Python并发编程|协程

    一.协程 协程,又叫微线程,纤程.英文名Coroutine.协程本质上就是一个线程 优点1:协程极高的执行效率.因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线 ...

  5. Python并发编程协程(Coroutine)之Gevent

    Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporate routine的缩写,直接翻译 ...

  6. python 并发编程 协程 协程介绍

    协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的 需要强调的是: 1. python的线程属于内 ...

  7. Python并发编程-协程

    利用Greenlet模块在多线程之间切换 from greenlet import greenlet def eat(): print('eating start') g2.switch() prin ...

  8. python 并发编程 协程池

    协程池 from gevent.pool import Pool from gevent import monkey;monkey.patch_all() import gevent from gev ...

  9. Python并发编程-协程实现socketserver

    #server.py from gevent import monkey;monkey.patch_all() import socket import gevent sk = socket.sock ...

随机推荐

  1. DAY 25多态、反射、异常处理

    一.面向对象与面向过程分析 1.print(len('123')) # 面向过程 #清晰知道操作的功能,但不能明确操作的具体对象,需要传入参数. 2.print('123'.__len__()) # ...

  2. windows,用c++调用mxnet做前向

    参考博客: https://blog.csdn.net/qq_34062105/article/details/82590553 https://blog.csdn.net/u012234115/ar ...

  3. python两个列表合并为字典,一个作为key,一个作为value

    两个列表合并为一个字典函数list_dic(list1,list2)可以直接复制拿走 传入的参数为两个列表,list1准备作为key,list2准备作为value,key和value位置一一对应. d ...

  4. POJ-2796 & 2019南昌邀请赛网络赛 I. 区间最大min*sum

    http://poj.org/problem?id=2796 https://nanti.jisuanke.com/t/38228 背景 给定一个序列,对于任意区间,min表示区间中最小的数,sum表 ...

  5. git设置用户名和邮箱

    用git config --global user.name "your name"命令来设置你的用户名 用git config --global user.email " ...

  6. ArcGIS中删除“点”附带的对应“文本信息”

    现状: 用ArcMap打开对应的.mxd文件,导入KML数据后,几何类型“点” - 每一个点都附带对应的文本信息“Placemark”,如下图: 问题:ArcGIS中如何 删除“点”附带的对应“文本信 ...

  7. Mac OS X 绑定80端口,不装nginx的小技巧

    Mac OS X 因为要绑定80端口需要ROOT权限, 但是如果用root权限启动eclipse或tomcat又会造成, 启动创建的各类文件是root的,普通用户无法删除. 为此, 我们可以通过pfc ...

  8. 刷题upupup【Java中HashMap、HashSet用法总结】

    HashMap: 常用操作 1. containsKey() 判断HashMap是否包含key 2. containsValue() 判断HashMap是否包含“值为value”的元素 3. get( ...

  9. Java加密算法

    密码的常用术语: 1.密码体制:由明文空间.密文空间.密钥空间.加密算法和解密算法5部分组成. 2.密码协议:也称为安全协议,是指以密码学为基础的消息交换的通信协议,目的是在网络环境中提供安全的服务. ...

  10. --save-dev --save 的区别

    --save 是发布会还在使用 --save-dev 是在开发中需要用到的 --save 依赖的文件在denpendencis下 --save-dev 依赖的文件都在dvedependencis下