python gevent實踐應用范例

python gevent實踐

gevent主要是用來實現python的并發處理的,并發的核心思想是將較大的任務分解為一組子任務,這些子任務被安排為同時或異步運行,而不是一次一個或同步運行。 兩個子任務之間的切換稱為上下文切換。

gevent中的上下文切換是通過yielding完成的。下面通過一些代碼來直觀感受gevent的用法。

  • 兩個通過調用gevent.sleep, 相互產生的兩個上下文, gevent會自動幫我們切換上下文處理

import gevent 

def foo():
  print("Running in foo")
  gevent.sleep(0)
  print("再次顯性地切換上下文到foo")

def bar():
  print("顯性地切換上下文到bar")
  gevent.sleep(0)
  print("程序暗地自動切換回上下文到bar")

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



  • 幾個處理邏輯并行處理的例子

import gevent 
import time 
from gevent import select 

start = time.time()
tic = lambda:  'at %1.1f seconds' % (time.time() - start)


def gr1():
  # 程序在這里處理需要點時間, 但是我們并不希望程序停在這里
  print("gr1 開始輪詢: %s" % tic())
  select.select([], [], [], 2)
  print('gr1 結束輪詢: %s' % tic())

def gr2():
  # 程序在這里處理需要點時間, 但是我們并不希望程序停在這里
  print('gr2 開始輪詢: %s' % tic())
  select.select([], [], [], 2)
  print('gr2 結束輪詢: %s' % tic())

def gr3():
  print('輪詢需要2秒,這個時候gr3 可以做一些其他的邏輯處理, 當程序在輪詢的時候, 等你妹啊, %s' % tic())
  gevent.sleep(1)


gevent.joinall([
  gevent.spawn(gr1),
  gevent.spawn(gr2),
  gevent.spawn(gr3),
])



  • 同步處理和異步處理的區別

import gevent
import random

def task(pid):
  """
  處理結果不確定的任務
  """
  gevent.sleep(random.randint(0, 2) * 0.001)
  print("任務 %s done" % pid)


def syncDo():
  for i in range(1, 10):
    task(i)

def asyncDo():
  threads = [gevent.spawn(task, i) for i in range(10)] 
  gevent.joinall(threads)

print("同步處理...")
syncDo()

print("異步處理...")
asyncDo()



  • 并行請求網絡資源

import gevent.monkey
gevent.monkey.patch_socket()

import gevent
import urllib.request
import simplejson as json

def fetch(pid):
    response = urllib.request.urlopen('http://quan.suning.com/getSysTime.do')
    result = response.read()
    json_result = json.loads(result)
    datetime = json_result['sysTime2']

    print('Process %s: %s' % (pid, datetime))
    return json_result['sysTime2']

def synchronous():
    for i in range(1,10):
        fetch(i)

def asynchronous():
    threads = []
    for i in range(1,10):
        threads.append(gevent.spawn(fetch, i))
    gevent.joinall(threads)

print('Synchronous:')
synchronous()

print('Asynchronous:')
asynchronous()




  • 異步通信達到線程等待的目的

import gevent
from gevent.event import Event 


evt = Event()

def setter():
  print("A: 請等待我,我正在做一些事情...")
  gevent.sleep(3)
  print("OK, 我已經完成了")
  evt.set()

def waiter():
  print("我在等待你")
  evt.wait()
  print("已經等待完成。。。")

def main():
  gevent.joinall([
    gevent.spawn(setter),
    gevent.spawn(waiter),
    gevent.spawn(waiter),
    gevent.spawn(waiter),
    gevent.spawn(waiter),
    gevent.spawn(waiter),
  ])


if __name__ == "__main__": main()



  • 利用隊列輕松完成job/woker代碼邏輯模型

import gevent
from gevent.queue import Queue, Empty

tasks = Queue(maxsize = 3)

def worker(name):
  try:
    while True:
      task = tasks.get(timeout = 1)    # 
      print("worker %s 正在處理任務 %s" % (name, task))
      gevent.sleep(0)
  except Empty:
    print("隊列處理完成, 退出")


def boss():
  for i in range(1, 10):
    tasks.put(i)
  print("已經分配完所有任務給 worker1, work1會迭代處理...")

  for i in range(10, 20):
    tasks.put(i)  
  print("已經分配完所有任務給 worker2, work1會迭代處理...")

gevent.joinall([
  gevent.spawn(boss),
  gevent.spawn(worker, "steven"),
  gevent.spawn(worker, "john"),
  gevent.spawn(worker, "bob"),
])


  • Erlang的ACTOR處理模型, 模擬發射器 和 接收器并行處理

# actor
import gevent
from gevent.queue import Queue 

class Actor(gevent.Greenlet):

  def __init__(self):
    self.inbox = Queue()
    Greenlet.__init__(self)

  def recv(self, msg):
    raise NotImplemented()

  def _run(self):
    self.running = True

    while self.running:
      msg = self.inbox.get()
      self.recv(msg)



# ping & pong
import gevent
from gevent.queue import Queue 
from gevent import Greenlet 

class Pinger(Actor):
  def recv(self, msg):
    print(msg)
    pong.inbox.put("ping")
    gevent.sleep(0)

class Ponger(Actor):
  def recv(self, msg):
    print(msg)
    ping.inbox.put("pong")
    gevent.sleep(0)

ping = Pinger()
pong = Ponger()

ping.start()
pong.start()

ping.inbox.put("start")
gevent.joinall([ping, pong])



其他應用要在實踐中使用體會。

本文鏈接:參與評論 ?

--EOF--

提醒:本文最后更新于 191 天前,文中所描述的信息可能已發生改變,請謹慎使用。

專題「后端」的其它文章 ?

Comments

toto足球指数