• python中的asyncio模块


    asyncio异步IO,能够异步网络操作,并发,协程

    1、asyncio的关键字说明

    • event_loop事件循环:程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的协程函数
    • coroutine协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象,协程对象需要注册到事件循环,由事件循环调用。
    • task任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含了任务的各种状态
    • future:代表将来执行或没有执行的任务结果。它和task上没有本质上的区别
    • async/await关键字:async定义一个协程,await用于挂起阻塞的异步调用接口,在python3.4是使用asyncio.coroutine/yield from

    2、定义一个协程

    # -*-coding:utf-8 -*-
    import asyncio
    async def func():
        print("waiting----func------")
    #这里是一个协程对象,这个时候func()函数并没有执行
    coroutine = func()
    print("coroutine",coroutine)
    #创建一个循环时间loop
    loop = asyncio.get_event_loop()
    #将协程加入到事件循环loop
    loop.run_until_complete(coroutine)
    loop.close()
    
    #输出:
    coroutine <coroutine object func at 0x02D10AE0>
    waiting----func------
    

    协程并发

    # -*-coding:utf-8 -*-
    import asyncio
    #定义一个协程比普通的函数多了async关键字
    async def a():
        print("waiting ----a-----")
        #在协程中挂起(释放控制权),await后面接的方法必须是awaitable的
        await asyncio.sleep(0)
        print("ending ------a---------")
    
    async def b():
        print("In b")
    
    async def main():
        #并发运行任务,另一种写法:asyncio.wait([a(),b()],)
        await asyncio.gather(a(),b())
    if __name__ == "__main__":
       """python3.6
        loop = asyncio.get_event_loop()
        loop.run_until_complete(main())
        loop.close()"""
       #启动循环事件,python3.7新写法
       asyncio.run(main())
       
     #输出:
     #waiting ----a-----
     #In b
     #ending ------a---------
    

    创建一个task

    协程对象不能直接运行,在注册事件循环的时候,其实是run_until_complete方法将协程包装成为了一个任务(task)对象,task对象是Future类的子类保存了协程运行后的状态,用于未来获取协程的结果

    # -*-coding:utf-8 -*-
    import asyncio
    import time
    now = lambda :time.time()
    async def do_some_work(x):
        print("waiting:",x)
    start = now()
    coroutine = do_some_work(2)
    loop = asyncio.get_event_loop()
    #创建task
    task = loop.create_task(coroutine)
    print("task",task)
    loop.run_until_complete(task)
    print("task--",task)
    print("Time:",now()-start)
    #输出
    task <Task pending coro=<do_some_work() running at D:/soft_install/python3/python3.7/StudyHard/OneDay/CheckCrawl/asyn.py:5>>
    waiting: 2
    task-- <Task finished coro=<do_some_work() done, defined at D:/soft_install/python3/python3.7/StudyHard/OneDay/CheckCrawl/asyn.py:5> result=None>
    Time: 0.0
    

    由输出可以看出创建task后,在task加入事件循环之前为pending状态,当完成后,状态为finished

    关于上面通过loop.create_task(coroutine)创建task,同样的可以通过 asyncio.ensure_future(coroutine)创建task

    绑定回调

    绑定回调,在task执行完成的时候可以获取执行的结果,回调的最后一个参数是future对象,通过该对象可以获取协程的返回值

    # -*-coding:utf-8 -*-
    import asyncio
    import time
    now = lambda :time.time()
    async def do_some_work(x):
        print("waiting:",x)
        return "Done after {}s".format(x)
    
    def callback(future):
        print("callback:",future.result())
    start = now()
    coroutine = do_some_work(2)
    loop = asyncio.get_event_loop()
    #创建task
    task = asyncio.ensure_future(coroutine)
    print("task:",task)
    task.add_done_callback(callback)
    print("task_add_callback:",task)
    loop.run_until_complete(task)
    print("Time:",now()-start)
    
    #输出
    task: <Task pending coro=<do_some_work() running at D:/soft_install/python3/python3.7/StudyHard/OneDay/CheckCrawl/asyn.py:5>>
    task_add_callback: <Task pending coro=<do_some_work() running at D:/soft_install/python3/python3.7/StudyHard/OneDay/CheckCrawl/asyn.py:5> cb=[callback() at D:/soft_install/python3/python3.7/StudyHard/OneDay/CheckCrawl/asyn.py:9]>
    waiting: 2
    callback: Done after 2s
    Time: 0.0
    
    

    通过add_done_callback方法给task任务添加回调函数,当task(也可以说是coroutine)执行完成的时候,就会调用回调函数。并通过参数future获取协程执行的结果。这里我们创建 的task和回调里的future对象实际上是同一个对象

    asyncio支持tcp,不支持http

    http是建立在tcp之上,可以基于用socket基于tcp做http的异步io

    简单的原理如下程序:

    import socket
    #创建一个客户端
    client = socket.socket()
    client.connect(("www.baidu.com",80,))
    content="Http1.1 /index.html?k1=k2 POST k1=k2
    
    username=a1&password=1234"
    #www.baidu.com/index.html?k1=k2
    content = bytes(content,encoding="utf-8")
    client.sendall(content)
    

    使用异步io做的http如下程序:

    # -*-coding:utf-8 -*-
    import asyncio
    import time
    async def fetch_async(host,url="/"):
        print(host,url)
        #客户端连接服务器,reader读取连接获取的数据,writer是发送写给服务器的数据
        reader,writer=await asyncio.open_connection(host,80)
        request_header_content = """GET %s HTTP/1.0
    Host:%s
    
    """ % (url,host,)
        request_header_content = bytes(request_header_content,encoding="utf-8")
        #写数据,发送
        writer.write(request_header_content)
        await writer.drain()
        #读取,这里也会阻塞
        text = await reader.read()
        print(host,url,str(text,encoding="utf-8"))
        writer.close()
    
    tasks=[
        fetch_async("www.cnblogs.com",'/wupeiqi/'),
        fetch_async("dig.chouti.com","/pic/show?nid=4073644713430508&lid=10273091")
    ]
    loop = asyncio.get_event_loop()
    results = loop.run_until_complete(asyncio.gather(*tasks))
    loop.close()
    

    关于上面的基于tcp做的异步io的http可以使用aiohttp模块,或者使用requests模块

    # -*-coding:utf-8 -*-
    import asyncio
    import time
    import aiohttp
    async def fetch_async(url):
        print(url)
        reponse = await aiohttp.request("GET",url)
        print(url,reponse)
        reponse.close()
    
    tasks=[
        fetch_async("www.cnblogs.com"),
        fetch_async("dig.chouti.com")
    ]
    loop = asyncio.get_event_loop()
    results = loop.run_until_complete(asyncio.gather(*tasks))
    loop.close()
    

    来自:1、https://www.jianshu.com/p/2eaf07770e79
    2、https://www.cnblogs.com/zhaof/p/8490045.html

  • 相关阅读:
    Selenium2(webdriver)入门之TestNG的使用
    selenium2.0(WebDriver) API
    xss漏洞校验
    文件上传攻击
    代码注入
    一个安全测试的CheckList
    MTK Android 设置-选择日期格式 [管理和组织首选项,ListPreference,CheckBoxPreference,EditTextPreference,RingtonePreference]
    MTK Android ListPreference的用法
    MTK Android 回调机制[CallBack]
    MTK Android 耳机线控的实现方法
  • 原文地址:https://www.cnblogs.com/venvive/p/11645229.html
Copyright © 2020-2023  润新知