简单介绍Python中利用生成器实现的并发编程


Posted in Python onMay 04, 2015

我们都知道并发(不是并行)编程目前有四种方式,多进程,多线程,异步,和协程。

多进程编程在python中有类似C的os.fork,当然还有更高层封装的multiprocessing标准库,在之前写过的python高可用程序设计方法中提供了类似nginx中master process和worker process间信号处理的方式,保证了业务进程的退出可以被主进程感知。

多线程编程python中有Thread和threading,在linux下所谓的线程,实际上是LWP轻量级进程,其在内核中具有和进程相同的调度方式,有关LWP,COW(写时拷贝),fork,vfork,clone等的资料较多,这里不再赘述。

异步在linux下主要有三种实现select,poll,epoll,关于异步不是本文的重点。

说协程肯定要说yield,我们先来看一个例子:

#coding=utf-8
import time
import sys
# 生产者
def produce(l):
  i=0
  while 1:
    if i < 5:
      l.append(i)
      yield i
      i=i+1
      time.sleep(1)
    else:
      return
   
# 消费者
def consume(l):
  p = produce(l)
  while 1:
    try:
      p.next()
      while len(l) > 0:
        print l.pop()
    except StopIteration:
      sys.exit(0)
l = []
consume(l)

在上面的例子中,当程序执行到produce的yield i时,返回了一个generator,当我们在custom中调用p.next(),程序又返回到produce的yield i继续执行,这样l中又append了元素,然后我们print l.pop(),直到p.next()引发了StopIteration异常。

通过上面的例子我们看到协程的调度对于内核来说是不可见的,协程间是协同调度的,这使得并发量在上万的时候,协程的性能是远高于线程的。

import stackless
import urllib2
def output():
  while 1:
    url=chan.receive()
    print url
    f=urllib2.urlopen(url)
    #print f.read()
    print stackless.getcurrent()
   
def input():
  f=open('url.txt')
  l=f.readlines()
  for i in l:
    chan.send(i)
chan=stackless.channel()
[stackless.tasklet(output)() for i in xrange(10)]
stackless.tasklet(input)()
stackless.run()

关于协程,可以参考greenlet,stackless,gevent,eventlet等的实现。

Python 相关文章推荐
在Python的Django框架中加载模版的方法
Jul 16 Python
Python实现视频下载功能
Mar 14 Python
pycharm安装图文教程
May 02 Python
浅谈python迭代器
Nov 08 Python
使用Python+Splinter自动刷新抢12306火车票
Jan 03 Python
Python基于高斯消元法计算线性方程组示例
Jan 17 Python
numpy.delete删除一列或多列的方法
Apr 03 Python
详解将Django部署到Centos7全攻略
Sep 26 Python
Python 从相对路径下import的方法
Dec 04 Python
python多线程下信号处理程序示例
May 31 Python
Django 外键的使用方法详解
Jul 19 Python
Python获取excel内容及相关操作代码实例
Aug 10 Python
简单分析Python中用fork()函数生成的子进程
May 04 #Python
python实现从字典中删除元素的方法
May 04 #Python
Python中利用原始套接字进行网络编程的示例
May 04 #Python
python通过索引遍历列表的方法
May 04 #Python
python实现将元祖转换成数组的方法
May 04 #Python
编写Python脚本来获取mp3文件tag信息的教程
May 04 #Python
python通过定义一个类实例作为ftp回调方法
May 04 #Python
You might like
php 广告调用类代码(支持Flash调用)
2011/08/11 PHP
linux下编译安装memcached服务
2014/08/03 PHP
PHP常用技巧汇总
2016/03/04 PHP
PHP中子类重载父类的方法【parent::方法名】
2016/05/06 PHP
一些主流JS框架中DOMReady事件的实现小结
2011/02/12 Javascript
实现点击列表弹出列表索引的两种方式
2013/03/08 Javascript
jQuery鼠标悬浮链接弹出跟随图片实例代码
2016/01/08 Javascript
全面了解javascript中的错误处理机制
2016/07/18 Javascript
JavaScript每天必学之数组和对象部分
2016/09/17 Javascript
详解React项目的服务端渲染改造(koa2+webpack3.11)
2018/03/19 Javascript
在 Angular-cli 中使用 simple-mock 实现前端开发 API Mock 接口数据模拟功能的方法
2018/11/28 Javascript
vue-router重定向和路由别名的使用讲解
2019/01/19 Javascript
Vue指令指令大全
2019/02/09 Javascript
详解javascript脚本何时会被执行
2021/02/05 Javascript
[05:09]2016国际邀请赛中国区预选赛淘汰赛首日精彩回顾
2016/06/29 DOTA
[43:24]2018DOTA2亚洲邀请赛3月29日 小组赛A组 LGD VS Liquid
2018/03/30 DOTA
python中偏函数partial用法实例分析
2015/07/08 Python
Python的Django框架中使用SQLAlchemy操作数据库的教程
2016/06/02 Python
详解pandas安装若干异常及解决方案总结
2019/01/10 Python
Django urls.py重构及参数传递详解
2019/07/23 Python
Windows下PyCharm2018.3.2 安装教程(图文详解)
2019/10/24 Python
使用批处理脚本自动生成并上传NuGet包(操作方法)
2019/11/19 Python
解决Keras 与 Tensorflow 版本之间的兼容性问题
2020/02/07 Python
浅谈python print(xx, flush = True) 全网最清晰的解释
2020/02/21 Python
python统计函数库scipy.stats的用法解析
2020/02/25 Python
python爬虫请求头的使用
2020/12/01 Python
css3如何绘制一个圆圆的loading转圈动画
2018/01/09 HTML / CSS
Europcar意大利:汽车租赁
2019/07/07 全球购物
计算机个人求职信范例
2014/01/24 职场文书
企业办公室主任岗位职责
2014/02/19 职场文书
2014四风问题对照检查材料范文
2014/09/15 职场文书
2014年预备党员群众路线教育实践活动对照检查材料思想汇报
2014/10/02 职场文书
党的群众路线教育实践活动领导班子整改方案
2014/10/25 职场文书
2014教师年度工作总结
2014/11/10 职场文书
2014年营业员工作总结
2014/11/18 职场文书
实习感想范文
2015/08/10 职场文书