协程,greenlet原生协程库, gevent库

yield表达式

  在了解协程之前,需要先了解一下生成器中的yield,它不仅可以当做生成器,还能当做一个表达式来使用(yield)

def func():
    x = (yield)
    print(x)
    x = (yield)

g = func()
print(next(g))  # 这是第一个yield,就暂停了
g.send(‘hello world‘)   # 恢复暂停位置,将第一个yield赋值,
                        # x = hello world,然后又执行到yield,暂停

-->
None
hello world

Process finished with exit code 0

需要注意的是:    send跟next一样,可以继续暂停的执行,并把send括号里面的东西变成返回值

        没有next开始,就不能使用send!

协程下的生产者与消费者问题

import random, time

def consumer():
    while True:
        item = (yield)  # 接收send的传递内容
        print(‘消费了%s‘ % item)
        time.sleep(1)

def producer(consumer): # 主函数
    next(consumer)  # 开启协程
    while True:
        item = random.randint(0, 99)
        print(‘生产了%s‘ % item)
        consumer.send(item)     # 发送
        time.sleep(1)

c = consumer()  # 生成器对象
producer(c)   

greenlet原生协程

  greenlet属于三方库,通过 pip install greenlet 安装

  什么是greenlet呢?

    CPython(标准python)能够通过生成器来实现协程,但使用起来并不方便而python的衍生版Stackless python,实现了原生的协程,便于利用。

    于是将stackless中关于协程的代码单独拿出来做成了CPython的扩展包

    也就是python环境下的原生协程包

  greenlet的价值

    一  高性能的远程协程

    二   语义更加明确的显示切换

    三   直接将函数包装成协程,保持原有代码风格

greenlet下的生产者与消费者问题

from greenlet import greenlet
from time import sleep
from random import randint

def consumer():
    while True:
        item = p.switch()   # 切换p,开始暂停,等待恢复(只有恢复的时候才能收到数据)
        print(‘消费了%s‘ % item)
        sleep(1)

def producer():
    while True:
        item = randint(0, 99)
        print(‘生产了%s‘ % item)
        c.switch(item)      # 暂停当前协程,并且切换到指定的协程,传参
        sleep(1)

c = greenlet(consumer)  # 直接封装成协程
p = greenlet(producer)
c.switch()  # 相当于next的作用,开启协程

 gevent协程

  什么是gevent?

    gevent开始之前可以先了解一下IO多路复用的epoll

    gevent通过封装了libev(基于epoll)和greenlet两个库,可以实现类似线程方式的协程

    gevent = epoll + greenlet

  gevent的价值是什么?

    遇到阻塞就切换到另一个协程继续执行

      一  使用基于epoll的libev来避开阻塞

      二   使用基于gevent的高效协程来切换执行

      三   只有阻塞的时候切换,没有轮询的开销,也没有线程的开销

gevent实现并发服务器

from gevent import monkey; monkey.patch_socket()
# 猴子补丁,将socket替换成一个封装了epoll的socket
from socket import socket
import gevent

server = socket()   # 封装好的socket
server.bind((‘‘, 7788))
server.listen(1000)

def recv(conn):
    while True:
        recv_date = conn.recv(1024).decode()
        if recv_date:
            print(recv_date)
            conn.send(recv_date.encode())
        else:
            conn.close()

while True:
    conn, addr = server.accept()
    # 生成一个协程,并将conn作为参数传入
    gevent.spawn(recv, conn)

gevent实现生产者与消费者问题

import gevent
from gevent import monkey; monkey.patch_all()
# all是所有的能切换成协程的地方全部切换,他包含了socket,一般情况下都是用all
from random import randint
from time import sleep
from gevent.queue import Queue  # gevent里面的队列

queue = Queue(3)

def consumer():
    while True:
        item = queue.get()  # 空就阻塞
        print(‘消费了%s‘ % item)
        sleep(1)

def producer():
    while True:
        item = randint(0, 99)
        queue.put(item)     # 满就阻塞 epoll阻塞就切换
        print(‘生产了%s‘ % item)
        sleep(1)

c = gevent.spawn(consumer)  #封装成协程
p = gevent.spawn(producer)
gevent.joinall([c, p])  # 等待传入协程结束

原文地址:https://www.cnblogs.com/pywjh/p/9516968.html

时间: 2024-08-28 12:23:17

协程,greenlet原生协程库, gevent库的相关文章

基于协程的Python网络库gevent

import gevent def test1(): print 12 gevent.sleep(0) print 34 def test2(): print 56 gevent.sleep(0) print 78 gevent.joinall([ gevent.spawn(test1), gevent.spawn(test2), ]) 解释下,"gevent.spawn()"方法会创建一个新的greenlet协程对象,并运行它."gevent.joinall()"

python协程初步--gevent库使用以及解释什么是猴子补丁monkey_patch

协程工作的特点是遇到阻塞或耗时的任务时就切换,协程的生存依赖于线程,线程依赖于协程 一个似乎有点问题的例子 import gevent,time def kisscpc(num): for i in range(num): print ("吻了第%s下陈培昌"%(i+1),gevent.getcurrent()) time.sleep(1) def kisscj(num): for i in range(num): print ("吻了第%s下程劲"%(i+1),g

Python 线程----线程方法,线程事件,线程队列,线程池,GIL锁,协程,Greenlet

主要内容: 线程的一些其他方法 线程事件 线程队列 线程池 GIL锁 协程 Greenlet Gevent 一. 线程(threading)的一些其他方法 from threading import Thread import threading import time def work(): time.sleep(1) print("子线程对象>>>", threading.current_thread()) # 子线程对象 print("子线程名称>

小议Python3的原生协程机制

此文已由作者张耕源授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 在最近发布的 Python 3.5 版本中,官方正式引入了 async/await关键字.在 asyncio [1] 标准库中实现了IO多路复用.原生协程(coroutine)与 事件循环(event loop),让人耳目一新,本文也尝试对 Python 3.5 新增加的原生协程 机制与asyncio标准库相关的内容做一个小结. IO多路复用与协程的引入,可以极大的提高高负载下程序的IO性能表现.几年前,

网络编程之协程——greenlet模块

网络编程之协程--greenlet模块 greenlet模块 如果我们在单个线程内有20个任务,要想实现在多个任务之间切换,使用yield生成器的方式过于麻烦(需要先得到初始化一次的生成器,然后再调用send...非常麻烦),而使用greenlet模块可以非常简单地实现这20个任务直接的切换 #安装:pip3 install greenlet from greenlet import greenlet def eat(name): print('%s eat 1' %name) g2.switc

Python的异步编程[0] -> 协程[1] -> 使用协程建立自己的异步非阻塞模型

使用协程建立自己的异步非阻塞模型 接下来例子中,将使用纯粹的Python编码搭建一个异步模型,相当于自己构建的一个asyncio模块,这也许能对asyncio模块底层实现的理解有更大的帮助.主要参考为文末的链接,以及自己的补充理解. 完整代码 1 #!/usr/bin/python 2 # ============================================================= 3 # File Name: async_base.py 4 # Author: L

为什么原生 JavaScript 开发越来越多受欢迎?是否应该跟风用原生JavaScript代替 jQuery等库?

本文标签:  jQuery的作用 原生JavaScript优势 jQuery官网 jQuery处理DOM和跨浏览器 JavaScript新特性 互联网杂谈 随着 JavaScript 本身的完善,越来越多的人开始喜欢使用原生 JavaScript 开发代替各种库,其中不少人发出了用原生 JavaScript 代替 jQuery 的声音.这并不是什么坏事,但也不见得就是好事.如果你真的想把 jQuery从前端依赖库中移除掉,我建议你慎重考虑. 首先 jQuery 是一个第三方库.库存在的价值之一在

OTA“多角恋”:携程闪电入股同程、途牛

OTA"多角恋":携程闪电入股同程.途牛 2014年04月30日 16:38 来源:南方都市报 参与互动(0) "携程将把景点门票的现付业务接入同程,并向同程投资超过2亿美金,支持同程独立IPO."4月28日晚间,同程网CEO吴志祥以发布内部邮件的形式,"向大家报告一个好消息." 而就在十来天前,同程旅游刚与艺龙旅行网签署了战略合作协议.据业内知情人士透露,伴随此次入股,携程与同程之间签署了一份"缓冲期"协议.即一年后,同程将

EF框架下实现动态建库切库

引言: 从第一开始,我就想,我们要想建一整套数据库,一个人来注册了,我们就可以给它注册一个库,这个库中所有的表结构,都是先前就准备好了的,我想,这个真的用EF的CodeFirst实现就最好了.因为我们的所有的ViewModel都是齐全的,用ModelFirst是需要画实体关联图的,用DBFirst就不用说了. 实现思路: 前期用我们所有的Model实体都是很好收集的,因为代码都是事先写好的,大概有100多个实体,这些实体就要满足;一旦有人进行注册,我们就给他生成这么多表的一个数据库.原理很简单,