生成器

参考文章:  协程   gevent

生成器进阶

看个例子:

def gg():
n=''
i=0
while True:
n=yield i #通过send传入到n
if not n:
pass
else:
print 'hehe',n
i=100 #传进参数n的时候,使得i的值也变化了
i+=1
if __name__=='__main__':
a=gg()
print a.send(None)
print a.next()
print a.send(None)
print a.send(9)
print a.next()
a.close()

结果:

/usr/bin/python2. /home/dahu/PycharmProjects/SpiderLearning/request_lianxi/t7.thread..py

hehe 

可以看出

  • 生成器的send(None)方法等于next()方法,next()方法可以直接替换成for循环
  • 通过send(n)传递参数n进生成器,生成器里面通过yield关键字来获取参数的值

协程

我们利用这个特性,来学习一下协程

#!/usr/bin/python
# coding=utf-8
# __author__='dahu'
# data=2017-
#多线程更改变量
import time
def consumer():
r = ''
while True:
n = yield r
if not n:
return
print('[CONSUMER] Consuming %s...' % n)
time.sleep(0.5)
r = '200 OK'
def produce(c):
c.next()
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n) #给生成器里传参,同时获取生成器里的值
print('[PRODUCER] Consumer return: %s' % r)
c.close()
if __name__=='__main__':
c = consumer()
produce(c)

结果,

/usr/bin/python2. /home/dahu/PycharmProjects/SpiderLearning/request_lianxi/t7.thread..py
[PRODUCER] Producing ...
[CONSUMER] Consuming ...
[PRODUCER] Consumer return: OK
[PRODUCER] Producing ...
[CONSUMER] Consuming ...
[PRODUCER] Consumer return: OK
[PRODUCER] Producing ...
[CONSUMER] Consuming ...
[PRODUCER] Consumer return: OK
[PRODUCER] Producing ...
[CONSUMER] Consuming ...
[PRODUCER] Consumer return: OK
[PRODUCER] Producing ...
[CONSUMER] Consuming ...
[PRODUCER] Consumer return: OK Process finished with exit code

注意到consumer函数是一个generator(生成器),把一个consumer传入produce后:

  1. 首先调用c.next()启动生成器;

  2. 然后,一旦生产了东西,通过c.send(n)切换到consumer执行;

  3. consumer通过yield拿到消息,处理,又通过yield把结果传回;

  4. produce拿到consumer处理的结果,继续生产下一条消息;

  5. produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

gevent

Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。

gevent是第三方库,通过greenlet实现协程,其基本思想是:

当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。

由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成

直接看例子:

#!/usr/bin/python
#coding=utf-8
#__author__='dahu'
#data=2017-
from gevent import monkey; monkey.patch_all()
import gevent
import urllib2
def f(url):
print('GET: %s' % url)
resp = urllib2.urlopen(url)
data = resp.read()
print('%d bytes received from %s.' % (len(data), url)) gevent.joinall([
gevent.spawn(f, 'https://www.cnblogs.com/dahu-daqing/'),
gevent.spawn(f, 'https://www.liaoxuefeng.com/'),
gevent.spawn(f, 'https://www.baidu.com/'),
])

结果:  从结果看,3个网络操作是并发执行的,而且结束顺序不同,但只有一个线程。

/usr/bin/python2. /home/dahu/PycharmProjects/SpiderLearning/request_lianxi/t10.gevent.py
GET: https://www.cnblogs.com/dahu-daqing/
GET: https://www.liaoxuefeng.com/
GET: https://www.baidu.com/
bytes received from https://www.baidu.com/.
bytes received from https://www.liaoxuefeng.com/.
bytes received from https://www.cnblogs.com/dahu-daqing/. Process finished with exit code

python生成器 协程的更多相关文章

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

    如果认真读过上文的朋友,应该已经明白了yield from实现的底层generator到caller的上传数据通道是什么了.本文重点讲yield from所实现的caller到coroutine的向下 ...

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

    一. 从列表中yield  语法形式:yield from <可迭代的对象实例> python中的列表是可迭代的, 如果想构造一个生成器逐一产生list中元素,按之前的yield语法,是在 ...

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

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

  4. python gevent 协程

    简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...

  5. 关于Python的协程问题总结

    协程其实就是可以由程序自主控制的线程 在python里主要由yield 和yield from 控制,可以通过生成者消费者例子来理解协程 利用yield from 向生成器(协程)传送数据# 传统的生 ...

  6. {python之协程}一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二

    python之协程 阅读目录 一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二 一 引子 本 ...

  7. 【Python】协程

    协程,又称微线程,纤程.英文名Coroutine. 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在 ...

  8. 深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!

    本文参考:http://www.dabeaz.com/coroutines/   作者:David Beazley 缘起: 本人最近在学习python的协程.偶然发现了David Beazley的co ...

  9. Python之协程(coroutine)

    Python之协程(coroutine) 标签(空格分隔): Python进阶 coroutine和generator的区别 generator是数据的产生者.即它pull data 通过 itera ...

随机推荐

  1. 服务器上的 Git - 生成 SSH 公钥

    http://git-scm.com/book/zh/ch4-3.html 生成 SSH 公钥 如前所述,许多 Git 服务器都使用 SSH 公钥进行认证. 为了向 Git 服务器提供 SSH 公钥, ...

  2. vim切换显示器乱行问题解决

    http://note.youdao.com/noteshare?id=ccdad950ca154a6b1597cbe2ede07b81

  3. HDU 4352 数位dp

    XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. 「Python」19个python编写技巧

    1. 交换赋值 2. Unpacking 3. 使用操作符in 4. 字符串操作 5. 字典键值列表 6. 字典键值判断 7. 字典 get 和 setdefault 方法 8. 判断真伪 9. 遍历 ...

  5. 跟我一起写Makefile(四)

    书写命令———— 每条规则中的命令和操作系统Shell的命令行是一致的.make会一按顺序一条一条的执行命令,每条命令的开头必须以[Tab]键开头,除非,命令是紧跟在依赖规则后面的分号后的.在命令行之 ...

  6. [LeetCode] 24. Swap Nodes in Pairs ☆

    Given a linked list, swap every two adjacent nodes and return its head. For example, Given 1->2-& ...

  7. Win10环境下配置VScode的C++编译环境

    写前感想:前前后后,折腾好几次,最后还是在学长安利下,开始入坑vscode了.原因一个是小巧,还有就是vs新建工程码题的方式太消耗内存了,基本每个项目就是以MB为单位计算的,然后希望用这篇文章记录自己 ...

  8. JavaScript Promises 实现框架一览及对比

    In my previous post in Danish I looked at how to perform asynchronous calls by using promises. Now t ...

  9. 强大的jQuery网格插件 ParamQuery

    ParamQuery是一种轻量级的jQuery网格插件,基于用于用户界面控制.具有一致API的优秀设计模式jQueryUI Widget factory创建,能够在网页上展示各种类似于Excel和Go ...

  10. How to reset XiaoMi bluetooth headphone Youth edition.

    To reset the speaker 1. Long press the phone call button to shut off the speaker 2. Connect the char ...