【Rollo的Python之路】Python 協程 yield與gevent 學習筆記

Python 協程:

協程,又稱微線程,纖程。英文名 Coroutine.一句話說明什麼是協程: 協程是一種用戶態的輕量級線程。python

協程擁有本身的寄存器上下文和棧。協程調度切換時,將寄存器上下文和棧保存到其餘地方,在切回來的時候,git

恢復先前保存的寄存器上下文和棧。所以:協程能保留上一次調用時的狀態(即全部局部狀態的一個特定組合)github

每次過程重入時,就至關於進入上一次調用的狀態。換種說法,進入上一次離開時所處邏輯流的位置編程

 

協程的好處:

  • 無需線程上下文切換的開銷併發

  • 無需原子操做鎖定及同步的開始
  • 方便切換控制流,簡化編程模型
  • 高併發+高擴展性+低成本: 一個CPU支持上萬的協程都不是問題,全部很適合高併發處理

協程的缺點:

  • 沒法利用多核CUP,
  • 進行阻塞(Blocking)操做會阻塞個整個程序

 

1.1 yield協程:

import time
import queue

def consumer(name):
    print('--------------start------------')
    while True:
        new_baozi = yield
        print('%s is eating baozi %s' %(name,new_baozi))
        time.sleep(1)

def producer():
    r = con.__next__() #也能夠是Next(con)
    r = con2.__next__()
    n =0
    while n < 5:
        n += 1
        con.send(n)
        con2.send(n)
        print("\033[32;1m[producer]\033[0m is making baozi %s" % n)

if __name__ == "__main__":
    con = consumer('c1')
    con2 = consumer('c2')
    p = producer()

 

1.2 greanlet:

from greenlet import greenlet

def test1():
    print(12)
    gr2.switch()
    print(34)
    gr2.switch()

def test2():
    print(56)
    gr1.switch()
    print(78)

gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()

 

1.3 gevent協程:

import gevent

def foo():
    print('Running in foo...')
    gevent.sleep(1)
    print('explicit context switch to foo again')

def bar():
    print('explicit context to bar')
    gevent.sleep(2)
    print('Implicit context switch back to bar')

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

])

 

 

from urllib.request import urlopen
from gevent import monkey
import gevent
import urllib

def f(url):
    print('GET: %s' % url)
    resp = urllib.request.urlopen(url)
    data = resp.read()
    print('%d bytes received from %s.' % (len(data), url))

gevent.joinall([
        gevent.spawn(f, 'https://www.python.org/'),
        gevent.spawn(f, 'https://www.yahoo.com/'),
        gevent.spawn(f, 'https://github.com/'),
])

加monkey.patch_all(),很快高併發

from urllib.request import urlopen
from gevent import monkey
monkey.patch_all()
import gevent


def f(url):
    print('GET: %s' % url)
    resp = urlopen(url)
    data = resp.read()
    print('%d bytes received from %s.' % (len(data), url))

gevent.joinall([
        gevent.spawn(f, 'https://www.python.org/'),
        gevent.spawn(f, 'https://www.yahoo.com/'),
        gevent.spawn(f, 'https://github.com/'),
])
相關文章
相關標籤/搜索