首页 > 编程语言 >python之IO并发-阻塞IO 非阻塞IO IO多路复用 异步IO(协程)

python之IO并发-阻塞IO 非阻塞IO IO多路复用 异步IO(协程)

时间:2024-12-09 09:48:10浏览次数:3  
标签:fileno 协程 阻塞 IO poll data select

阻塞IO即为之前正常使用的IO 逻辑简单 非阻塞IO 可以把阻塞IO 设置为非阻塞IO,例如sockfd.setblocking(false)。如果设置成了非阻塞,无客户端连接时就会报BlockingIOError错误,通过try来捕获。通过循环来接受客户端连接

还可以设置超时检测,settimeout---sockfd.settimeout(5)超时报错

while True:
    print("Waiting from connect...")
    try:
        connfd,addr = sockfd.accept()
    except (BlockingIOError,timeout) as e:
        sleep(2)
        f.write("%s : %s\n"%(ctime(),e))
        f.flush()
    else:
        print("Connect from",addr)
        data = connfd.recv(1024).decode()
        print(data)

IO多路复用:select poll epoll

elect适用于window,Linux ,unix,poll:inux unix epoll:unix

select最多监控1024个IO

poll比select监控的IO数量多

epoll比select poll的效率高,监控的IO多,触发方式多

select:把要监测的IO放入rlist,wlist,xlist中,rlist适用于被动接受,wlist适用于主动写入,xlist出现错误出发(一般不用)。select()函数返回值也是3个列表,循环3个列表处理IO就绪事件

from select import select
from socket import *
s=socket()
s.bind(('0.0.0.0',8000))
s.listen(5)
 
rlist=[s]
wlist=[]
xlist=[]
while True:
    rs,ws,xs=select(rlist,wlist,xlist)
    for r in rs:
        if r==s:
            conf, addr = r.accept()
            print('监听到',addr,'的链接')
            rlist.append(conf)
        else:
            data=r.recv(1024)
            print(data)
            r.send(b'ok')
            if not data:
                r.close()
                rlist.remove(r)
    for w in ws:
        pass

poll:from select import poll

用到的函数有:p=poll()(建立poll对象),p.register(IO对象,POLLIN|POLLERR)(注册IO事件),p.unregister(IO对象或文件描述符) (取消注册)“event & POLLIN” 按位与检查是否检测POLLIN事件(读IO事件)。events=p.poll()(阻塞等待监控IO事件发生)events为列表里面套元组[(fileno,event),()] 要自己做fileno和IO对象的映射字典,动态维护字典

from select import *
from socket import *
s=socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(('0.0.0.0',8887))
s.listen(3)
p=poll()
fdmap={s.fileno():s}
p.register(s,POLLIN)
while True:
    events=p.poll()
    for fileno,event in events:
        if fileno==s.fileno():
            conf,addr=s.accept()
            p.register(conf,POLLIN|POLLERR)
            fdmap[conf.fileno()]=conf
        elif event & POLLIN:
            data=fdmap[fileno].recv(1024).decode()
            print(data)
            if not data:
            #客户端退出,unregister,字典删除,套接字关闭
                p.unregister(fileno)
                fdmap[fileno].close()
                del fdmap[fileno]
                continue
            fdmap[fileno].send(b'ok')

epoll使用方法和poll一样,要加E

协程

asyncio模块

普通函数def之前加async关键字 async def get_request()...
函数调用生成协程对象c=get_request()
创建任务对象 task=asyncio.ensure_future(c),多任务则需创建tasks列表,把task append到tasks里。loop.run_until_complete(asyncio.wait(tasks))
创建事件循环对象loop=asyncio.get_event_loop()
将任务对象装载在事件循环对象中启动事件循环对象loop.run_until_complete(task)
如果函数有返回值,则给任务对象绑定回调函数task.add_done_callback(task_callback)
回调函数必须有一个参数,data=参数.result(),data则为函数的返回值
await关键字:挂起发⽣阻塞操作的任务对象。 在任务对象表示的操作中,凡是阻塞操作的前⾯ 都必须加上await关键字进⾏修饰
如果用协程去获取网络请求就需要用到:aiohttp模块,aiohttp支持异步模块

在每⼀个with前加上async关键字

在阻塞操作前加上await关键字

async def get_request(url):
#requests是不⽀持异步的模块
# response = await requests.get(url=url)
# page_text = response.text
#创建请求对象(sess)
    async with aiohttp.ClientSession() as sess:
#基于请求对象发起请求
#此处的get是发起get请求,常⽤参数:url,headers,params,proxy
#post⽅法发起post请求,常⽤参数:url,headers,data,proxy
#发现处理代理的参数和requests不⼀样(注意),此处处理代理使⽤proxy='http://ip:port'
多任务异步爬⾍的完整代码实现:
    async with await sess.get(url=url) as response:
        page_text = await response.text()
#text():获取字符串形式的响应数据
#read():获取⼆进制形式的响应数据
    return page_text

第三方库模块:gevent模块

用到的函数:f=gevent.spawn(func,argv)(生成协程函数)gevent.joinall(list,[timeout])

导入monkey模块 from gevent import monkey
运行相应脚本 monkey.patch_socket()(很多脚本,需要自己选择自己需要的,或者patch_all())
脚本运行要在相应的模块导入之前

"""
gevent server 基于协成的tcp并发
思路 : 1. 每个客户函数端设置为协成
      2. 将socket模块下的阻塞变为可以触发协程跳转
"""
import gevent
from gevent import monkey
monkey.patch_all() # 执行脚本,修改socket
from socket import *
 
def handle(c):
    while True:
        data = c.recv(1024).decode()
        if not data:
            break
        print(data)
        c.send(b'OK')
    c.close()
 
# 创建tcp套接字
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(('0.0.0.0',8888))
s.listen(5)
 
# 循环接收来自客户端连接
while True:
    c,addr = s.accept()
    print("Connect from",addr)
    # handle(c) # 处理具体客户端请求
    gevent.spawn(handle,c) # 协程方案

 人工智能(PythonNet)—— 目录汇总

标签:fileno,协程,阻塞,IO,poll,data,select
From: https://www.cnblogs.com/bighan1/p/18594245

相关文章

  • .NET for Android/iOS应用的如何在各自的系统运行
    1..NETforAndroid上的运行机制Android应用使用Mono运行时或.NET运行时在Android设备上执行。具体过程如下:编译过程:C#代码编写:开发者使用C#编写业务逻辑代码。编译为IL:C#代码通过Roslyn编译器转换为中间语言(IL)。JIT或AOT编译:JIT(即时编译):在Androi......
  • 当页面中使用application/xhtml+xml会出现什么问题吗?
    使用application/xhtml+xml作为MIME类型在前端开发中可能会出现一些问题,尽管在理想情况下它应该提供更严格的验证和结构。主要问题源于浏览器对XHTML的支持不一致以及与旧版浏览器和服务器的兼容性问题。以下是可能出现的一些问题:浏览器兼容性:并非所有浏览器都完全支......
  • 如何关闭HTML页面在IOS下的键盘首字母自动大写?
    在iOS上关闭HTML页面键盘首字母自动大写,你可以使用autocapitalize属性并将其设置为off。这适用于所有支持该属性的HTML输入元素,例如<input>,<textarea>等。以下是如何操作的示例:<inputtype="text"autocapitalize="off"placeholder="输入文本"><textareaautoc......
  • 使用 Io 语言实现简单的图像处理
    什么是Io语言?Io是一种轻量级、面向对象且动态的编程语言,设计灵感来源于Smalltalk、Lisp和Lua。它以其简洁的语法和强大的元编程能力著称,非常适合快速实现概念验证或进行脚本编写。在本篇文章中,我们将使用Io编写一个简单的灰度图像反转(取反)处理程序。代码实现:灰度图像反......
  • PAWNYABLE kernel race condition 笔记
    漏洞点在于,open的时候mutex的检查和设置不是原子操作。staticintmodule_open(structinode*inode,structfile*file){printk(KERN_INFO"module_opencalled\n");if(mutex){printk(KERN_INFO"resourceisbusy");return-EBUSY;}mutex=......
  • PNG Images Compression method
    Version1.00Assignment–PNGImagesVersion1.00SubmissionGuidelinesDeadline:9:00AMonFriday13DecemberSubmissionprocedure:Submitonlyonefilelabelledpng.pythroughblackboard(viaTurnItIn)Versionrequirement:YourcodemustrunusingPython......
  • CCIT4020 Introduction to Computer
     CCIT4020IntroductiontoComputerProgrammingAssignment3–SectionCGeneralguidelines:Useconciseanddirecttechniques/programcodeswelearninourcourse.Uselessorover-complicatedtechniques/programcodesmaybeignoredorpenalized.Stud......
  • 置换与转置 permutations & transposes
    置换与转置permutations&transposes​ 首先说一下置换矩阵(permutationmatrix),通常记为\(\symbfit{P}\),是用来完成行互换操作的矩阵。\(\symbfit{P}_{i,j}\)记为第\(i\)行和第\(j\)行互换的置换矩阵。​ 例如三行三列方阵有\(3!=6\)个置换矩阵,如\(\symbfit{P}_{2,1}=\begin{bm......
  • C语言动态哆啦A梦源码分享,无需编程基础,小白轻松运行,顺便解决Visual Studio 2022里c++
    下面是运行效果图:首先是安装VisualStudio2022VisualStudio2022IDE-适用于软件开发人员的编程工具打开上面的网址,选择下载社区版 下载好后运行,进来以后,如果是初次安装需要下载安装,我的是原来就有的所以会显示更新,如果原来就有的请点击修改按钮,选择配置下载并安装......
  • Advent of Code 2022 solution [Mathematica/Scala/MATLAB/Julia/JavaScript]
    目录简介试题地址Day1Part1andPart2Day2Part1andPart2Day3Part1andPart2Day4Part1andPart2Day5Part1andPart2Day6Part1andPart2Day7Part1andPart2Day8Part1andPart2Day9Part1andPart2Day10Part1andPart2Day11Part1andPart......