python: 协程 小笔记(1)

协程:(微线程)用户态轻量级线程

    单线程,串行,其实质在不同的函数中快速切换,以达到并行的效果。适合io操作密集型工作中。

协程的好处:

  (1)无需线程上下文切换的开销

  (2)无需原子操作锁定及同步的开销

  (3)方便切换控制流,简化编程模型

  (4)高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

缺点:

  无法利用多核资源:协程的本质是个单线程,它不能同时将单个CPU的多个核用上,协程需要和进程配合才能运行在多CPU上.

当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。进行阻塞(Blocking)操作(如I0时)会阻塞掉整个程序

协程模块:

(1)greenlet :手动切换

  程序会按照注释先后执行。

import greenlet
def product():
    print('leo 来吃包子了')  #1
    g2.switch()
    print("急什么急,正在做")#3
    g2.switch()
    print('急毛线,信不信我下毒')#5

def consumer():
    print("包子呢?leo恶狠狠的说!")#2
    g1.switch()
    print('快一点,不然老子弄死你')#4
    g1.switch()
g1 = greenlet.greenlet(product)
g2 = greenlet.greenlet(consumer)
g1.switch()
greenlet

(2)gevent:自动切换,同步、异步 

import gevent

def foo():
    print(' Running in foo')  #1
    gevent.sleep(2)
    print(' Explicit context switch to foo again')#6

def bar():
    print('Explicit精确的context内容to bar')#2
    gevent.sleep(1)
    print (' Implicit context switch back to bar')#5

def run():
    print("runxxxxx")#3
    gevent.sleep(0)
    print("run end")#4

gevent.joinall(
[gevent.spawn(foo) ,
  gevent.spawn (bar),
 gevent.spawn(run)])
gevent 

一个非常low的爬虫demo:

from urllib import request
from gevent import monkey  #把当前程序的所有的有可能是io操作单独的做上标记
import gevent

monkey.patch_all()
def f(url):
    print('GET:%s'%url)

    resp =request.urlopen(url)
    data =resp.read()
    with open('url.html','wb') as f:
        f.write(data)

gevent.joinall(
    [gevent.spawn(f,'http://www.cnblogs.com/alex3714/articles/5248247.html'),
    gevent.spawn(f,'https://www.yahoo.com/'),
    gevent.spawn(f,'https://github.com/'),]
)
View Code

 

posted @ 2019-08-19 10:05  Forever_eif  阅读(134)  评论(0编辑  收藏  举报