协程:gevent模块,遇到i/o自动切换任务 038

协程 : gevent模块,遇到io自动切换任务

from gevent import monkey;monkey.patch_all()  # 写在最上面 这样后面的所有阻塞就全部能够识别了
import gevent  # 直接导入即可
from threading import current_thread
import time
def eat(name):
    print(‘%seat1‘% name)
    # gevent.sleep(2)
    time.sleep(2)   # 加上monkey就能
    print(‘%seat2‘% name)
    print(current_thread().getName())
def play(name):
    print(‘%splay1‘% name)
    # gevent.sleep(2)
    time.sleep(2)
    print(‘%splay2‘% name)
    print(current_thread().getName())
g1 = gevent.spawn(eat,‘egon‘)  # 创建一个协程对象 spawn括号内第一个参数是函数名
g2 = gevent.spawn(play,‘egon‘)
gevent.joinall([g1,g2]) # 将g1.join()和g2.join()合成一步写了出来
print(‘主‘)
# 结果为
# egoneat1
# egonplay1
# egoneat2
# DummyThread-1  # 假线程 虚拟线程 其实都在一个线程里面
# egonplay2
# DummyThread-2
# 主

    gevent.sleep(2)模拟的是gevent可以识别的io阻塞,

    而 time.sleep(2)或其他阻塞 是不能直接识别的 需要用下面一行代码打补丁 就可以识别了

    from gevent import monkey;monkey.patch_all() 放在time, socket之前 或者直接将其放在文件开头.

    协程是通过自己的程序实现切换 自己能够控制 只有遇到协程模块能够识别io操作的时候, 程序才会进行任务切换 实现并发效果 , 如果所有的程序都没有io操作 那么久基本属于串行执行了.

给大家看一个线程下(协程)来实现多个客户聊天

io多路复用:模型(解决问题方案)

#服务端
from socket import *
import select
server  = socket(AF_INET, SOCK_STREAM)
server.bind((‘127.0.0.1‘,8093))
server.listen(5)
# 设置为非阻塞
server.setblocking(False)
# 将初始化服务端socket对象加入监听列表 后面还要动态添加一些conn连接对象, 当accept的时候sk就有感应 , 当recv的时候conn就有动静
rlist = [server,]
rdata = {}  # 存放客户端发送过来的消息
wlist = []  # 等待写对象
wdata = {}  # 存放要返回客户端的消息
print(‘准备监听!‘)
count = 0 # 写着计数用的 为了看实验效果用的 , 没用
while 1:
    # 开始select监听,对rlist中服务端server进行监听 , select函数阻塞进程 , 直到rlist中套接字被触发(在此例中,套接字接收到客户端发来的握手信号 , 从而变得可读 满足select函数的可读条件),被触发的(有动静的)套接字(服务器套接字)返回给了rl这个返回值里面;
    rl,wl,xl = select.select(rlist,wlist,[],0.5)
    print(‘%s 次数>>‘%(count),wl)
    count = count + 1
    # 对rl进行循环判断是否有客户端连接进来 , 当有客户端连接进来时select将触发
    for sock in rl:
        # 判断当前触发的是不是socket对象, 当触发的对象是socket对象时说明有新客户端accept连接进来了
        if sock == server:
            # 接收客户端的连接, 获取客户端对象和客户端地址信息
            conn,addr = sock.accept()
            # 把新的客户端连接加入到监听列表中 当客户端连接有接受消息的时候 , select将会被触发 ,会知道这个链接有动静 , 有消息 , 那么返回geirl这个返回值列表里面
            rlist.append(conn)
        else:
            # 由于客户端连接进来时socket接收客户端请求 , 将客户端连接加入到了监听列表中(rlist),客户端发送消息的时候这个链接将触发
            # 所以判断是否是客户端连接对象触发
            try:
                data = sock.recv(1024)
                # 没有数据的时候,将这个连接关闭掉 , 并从监听列表中移除
                if not data:
                    sock.close()
                    rlist.remove(sock)
                    continue
                print(‘received{0} from client{1}‘.format(data.decode(),sock))
                # 将接收到的客户端的消息保存下来
                rdata[sock] = data.decode()
                # 将客户端连接对象和这个对象接受到的消息加工成返回消息 , 并添加到wdata这个字典里面
                wdata[sock] = data.upper()
                # 要给这个客户端回复消息的时候, 我们将这个链接添加到wlist监听列表中
                wlist.append(sock)
            # 如果这个连接出错了,客户端暴力断开了(注意 , 还没有接收到客户端的消息 , 或者接收消息的过程中出错了)
            except Exception:
                # 关闭这个连接
                sock.close()
                # 在监听列表中将他删除 , 因为不管什么原因 毕竟是断开了 没必要再监听他了
                rlist.remove(sock)
    # 如果现在没有客户端请求连接 也没有客户端发送消息时 , 开始对发送消息的列表进行处理 , 是否需要发送消息
    for sock in wl:
        sock.send(wdata[sock])
        wlist.remove(sock)
        wdata.pop(sock)
    # 将以此select监听列表中有接收数据的conn对象所接收到的消息打印一下
    # for k , v in rdata.items():
    #       print(k,‘发来的消息是‘,v)
    # # 清空接收到的消息
    #rdata.clear()

  知识总结 :

    1 cs架构 bs架构

    2 网络通信流程:

       网卡 mac地址 子网掩码 网关 dns服务器 dhcp nat(网络地址转换)  端口(表示电脑上某个应用程序)  路由器 交换机 集线器 广播 单播 广播风暴 ARP协议 路由协议

    3 网络网络通信协议(**)

      osi七层 应表会传网数物

      tcp\ip协议  应用层 网络层 数据链路层 物理层

      tcp(*****)

        三次握手 客-->服--->客

        四次挥手

        tcp和udp区别(*****)

          tcp: 面向连接 消息可靠 效率相对差 面向流的消息格式 无消息保护边界

          udp:面向无连接 不可靠 效率很高 面向包的消息格式 有消息保护边界

    4 socket

        缓冲区:

        粘包现象 : 1 连续发送小包并且间隔时间很短 就会发送两个消息合并在一起的情况 (Nagel优化算法导致的)  2 一次发送数据过大 对方一次未接收完 下次接受的时候连同第一次剩下的消息一同接受了 导致粘包

        解决粘包方案 都不知道对方发送的消息长度   1 发送消息之前先发送消息长度 收到对方确认信息后再次发送消息  2 通过struct 模块 自定义报头 将消息长度打包成4个字节长度的信息 连同你要发送的数据一并发过去

        打包 pack(‘i‘,长度)   长度是个整数

原文地址:https://www.cnblogs.com/f-g-f/p/9879942.html

时间: 2024-10-08 22:04:44

协程:gevent模块,遇到i/o自动切换任务 038的相关文章

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

网络编程之协程--gevent模块 gevent模块 安装 pip3 install gevent Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程. Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度. #用法 g1=gevent.spawn(func,1,,2,3,x=4,y=5)创建一个协程对象g1,spawn括号内第一个参数是函数名,如e

17、第七周-网络编程 - 协程概念介绍、协程gevent模块并发爬网页

协程,又称微线程,纤程.什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈.因此:协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置. 协程的好处: 无需线程上下文切换的开销 无需原子操作锁定及同步的开销(注解:"原子操作(atomic operation)是不需要synchr

线程池+协程+gevent模块

提交任务的两种方式: 同步调用:提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行的 异步调用:提交完一个任务之后,不在原地等待,而是直接执行下一行代码,会导致任务是并发执行的 p.shutdown(wait=True)关闭进程池的入口,并且在原地等待进程池内所有任务运行完毕 异步调用:提交完一个任务之后,不在原地等待,而是直接执行下一行代码,会导致任务是并发执行的,结果:futrue对象会在任务运行完毕后自动传给回调函数 在线程下实现

python 并发编程 协程 gevent模块

一 gevent模块 gevent应用场景: 单线程下,多个任务,io密集型程序 安装 pip3 install gevent Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程. Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度. gevent可以检测io,实现遇到io自动切换另外一个任务 #用法 g1=gevent.spawn(func,1,

网络编程之协程——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

tcp_server_协程gevent版本

#!/usr/bin/env python # -*- coding:utf-8 -*- # @Time : 2020/1/23 1:50 # @Author : liuyan # @File : test5_tcp_server_5协程gevent版本.py # @Software: PyCharm import gevent from gevent import monkey; monkey.patch_all() #使用此方法,会将代码中检查一遍,如有time.sleep()等延时方法,会

python协程gevent案例:爬取斗鱼美女图片

分析 分析网站寻找需要的网址 用谷歌浏览器摁F12打开开发者工具,然后打开斗鱼颜值分类的页面,如图: 在里面的请求中,最后发现它是以ajax加载的数据,数据格式为json,如图: 圈住的部分是我们需要的数据,然后复制它的网址为https://www.douyu.com/gapi/rknc/directory/yzRec/1,出于学习目的只爬取第一页(减少服务器压力).然后把网址放到浏览器中测试是否可以访问.如图: 结果正常. 分析json数据,提取图片链接 最后分析发现json中的data里面的

python2.0_s12_day9_协程&Gevent协程

Python之路,Day9 - 异步IO\数据库\队列\缓存 本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 协程 1.协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是协程:协程是一种用户态的轻量级线程.(操作系统跟不知道它存在),那你指定协程的实现原理是什么吗? 我们来聊聊协程的实现原理: 首先我们知道多个线程在一个单核CPU上进行并发,它的操作过程是,操作系统能调动的最小单位是线程,当操作系统触发多个线

协程-gevent

协程用gevent实现, 依赖libevent和greenlet###安装1. 安装libevent   yum install libevent 2. 安装easy_install  [1]wget -q http://peak.telecommunity.com/dist/ez_setup.py  [2]python ez_setup.py  [3]使用easy_install 查看命令是否可用,如果不可用可以讲路径加入到PATH中 3. 安装greenlet    [1]yum insta