1. 程式人生 > 程式設計 >Python 中由 yield 實現非同步操作

Python 中由 yield 實現非同步操作

yield在python中初學時,覺得比較難理解。yield的作用:

①返回一個值、②接收呼叫者的引數

分析下面的程式碼:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

def consumer():
  r = ''
  while True:
    n = yield r
    print("[Consumer] n = %d" %n)
    if not n:
      return
    print("[Consumer] consuming %s..." %n)
    r = '200 OK'

def produce(c):
  c.send(None)
  h = 0
  while h < 5:
    h = h + 1
    print("[Producer] producing %d..." %h)
    s = c.send(h)
    print("[Producer] consumer return: %s" %s)
  c.close()

c = consumer() #建立一個生成器
produce(c) #在該函式中,呼叫生成器的send()方法

Python 中由 yield 實現非同步操作

結合程式執行過程,可分析出:

第一步:

在produce(c)函式中,呼叫了c.send(None)啟動了生成器,遇到yield暫停;接著執行produce()中接下來的程式碼,從執行結果看,確實打印出了[Produce] producing 1 … 當程式執行至c.send(h)時,呼叫生成器並且通過yield傳遞了引數(h = 1)進入consumer()函式執行。

第二步:

yield傳遞引數(h=1)給consumer()函式中的n,並接著上一次暫停處往下繼續執行,打印出[Consumer] n = 1,[Consumer] consuming 1… ;在consumer()函式中此時 r 被賦值為'200 OK',接著迴圈遇到yield, consumer()函式又暫停並且返回變數 r 的值,此時程式又進入produce(c)函式中接著執行。

第三步:

produce(c)函式接著第一步中c.send(h)處,繼續往下執行打印出[Producer] consumer return: 200 OK,並進行迴圈,列印[Producer] producing 2… 後,又呼叫c.send(h) 。。。如此迴圈回到第一步!

補充知識:python asyncio模型 事件迴圈

非同步建立在事件迴圈上.

簡單來說事件迴圈:

1.把要執行的函式放入佇列

2.取出函式,執行

3.看看還要不要繼續放入此函式

4.繼續第一步

一個簡單的例子說明:

"""
  1.yield 掛起當前函式.
  2.使用排程器迴圈
  3.使用next喚醒此函式繼續執行
"""
def f1():
  for i in range(3):
    print('f1 %d'%i)
    yield
def f2():
  for i in range(5):
    print('f2 %d' %i)
    yield
def f3():
  for i in range(10):
    print('f3 %d'%i)
    yield
#模擬一個排程器
task_q = collections.deque((f1(),f2(),f3()))
#讓排程器排程這些生成器們
while task_q:
  task = task_q.popleft() #彈出首個生成器
  try:
    next(task)     #執行,如果沒有異常證明此生成器還沒執行完成,可以繼續放入佇列中
    task_q.append(task) #執行完成後,把任務繼續新增到佇列中.
    time.sleep(0.5)
  except StopIteration as ex:
    pass

以上這篇Python 中由 yield 實現非同步操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。