美文网首页
详解async 与 await,带您理解Playwright使用

详解async 与 await,带您理解Playwright使用

作者: 测试开发Kevin | 来源:发表于2023-05-07 11:45 被阅读0次

    大家在使用python做playwright自动化测试的过程中,一定会发现下面这种异步用法

    async def func():

          await api

          await api

    很多同学可能只是按照这种写法来编写项目的自动化测试代码,对于具体细节可能并不了解,今天我就来讲一下playwright异步用法的相关技术细节。建议大家拷贝文档中的脚本实际运行一下,学习的效果会更好!

    同步和异步的概念

    同步:发送一个请求,等待返回,然后再发送下一个请求

    异步:发送一个请求,不等待返回,随时可以再发送下一个请求

    async 与 await

    python在3.5以后引入async和await来强化自身的异步编程,提升效率。async 是异步的简写,而 await 可以认为是 async wait 的简写。async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。异步函数的特点是能在函数执行过程中挂起,去执行其他异步函数,等到挂起条件结束后再回来继续执行。await的作用是挂起函数,等待函数操作完成,这时候回去执行其他的异步函数,而不是傻等,等挂起的执行完成以后将会从其他异步函数处返回,执行挂起结束的函数。await只可以对异步函数使用,普通函数使用会报错。await的本质是通过yield from 实现的,关于yield生成器相关知识点这里就不详细介绍了。

    例如:两个异步程序async a、async b:

    a中一步有await,当程序碰到关键字await后,异步程序a挂起,去执行异步b程序(就相当于从一个函数内部跳出去执行其他函数);当挂起条件结束时候,不管b是否执行完,要马上从b程序中跳出来,回到原程序a执行原来的操作;如果await后面跟的b函数不是异步函数,那么操作就只能等b执行完再返回,无法在b执行的过程中返回,这样就相当于直接调用b函数,没必要使用await关键字了。因此,需要await后面跟的是异步函数。

    举个例子

    import time

    import asyncio

    async def wait1():

        print('wait1 start')

        await asyncio.sleep(1)

        print('wait1 end')

    async def wait3():

        print('wait3 start')

        await asyncio.sleep(3)

        print('wait3 end')

    async def wait5():

        print('wait5 start')

        await asyncio.sleep(5)

        print('wait5 end')

    # 2. 将异步函数加入事件队列

    tasks = [

        wait1(),

        wait3(),

        wait5(),

    ]

    if __name__ == '__main__':

        # 创建一个事件循环

        loop = asyncio.get_event_loop()

        startTime = time.time()

        # 执行队列实践,直到最晚的一个事件被处理完毕后结束

        loop.run_until_complete(asyncio.wait(tasks))

        # 如果不在使用loop,建议使用关闭,类似操作文件的close()函数

        loop.close()

        endTime = time.time()

        print("sum time: ",endTime-startTime)

    运行结果

    wait5 start

    wait3 start

    wait1 start

    wait1 end

    wait3 end

    wait5 end

    sum time:  5.000609874725342

    上面这段代码大家可以多执行几次,我们会发现:不管wait1 wait3,wait5 哪个函数先执行,但是最后end的顺序一定是 wait1>wait3>wait5。一共运行的时间 在5s左右,充分地证明了三个函数是并行执行的!

    接下来,我们可以对代码进行如下修改:

    async def wait3():

        print('wait3 start')

        time.sleep(3)

        print('wait3 end')

    然后再次运行代码,结果如下:

    wait5 start

    wait3 start

    wait3 end

    wait1 start

    wait1 end

    wait5 end

    sum time:  5.002418518066406

    大家会发现,只有wait3 end 发生后,才会出现wait1 end 和wait5 end(),很好的证明了上面的话:如果await后面跟的b函数不是异步函数,那么操作就只能等b执行完再返回,无法在b执行的过程中返回,这样就相当于直接调用b函数,没必要使用await关键字了。我们可以任意调整task的执行顺序,例如:

    tasks = [

        wait1(),

        wait5(),

        wait3(),

    ]

    执行最慢的情况就是,wait3 第一个start,等待wait3 end后,才能执行wait1 或者wait5

    wait3 start

    wait3 end

    wait5 start

    wait1 start

    wait1 end

    wait5 end

    sum time:  8.000799894332886

    一个易犯的错误

    当我们在同步方法中加入await,执行代码的时候会报错,也就是说像下面这样编写playwright脚步是不对的,因为sync_playwright() 是同步方法!

    from playwright.sync_api import sync_playwright

    with sync_playwright() as p:

    browser = p.chromium.launch(channel="chrome")

    page = browser.new_page()

    await page.goto("http://www.baidu.com")

    print(page.title())

    browser.close()

    Playwright使用异步方法的正确姿势

    如下代码会正常运行,通过await可以保证脚本的运行顺序

    async def playwright_async_demo():

      async with async_playwright() as p:

        browser = await p.chromium.launch(channel="chrome")

        page = await browser.new_page()

        await page.goto("http://www.baidu.com")

    asyncio.run(playwright_async_demo())

    如果我们把上面代码中 browser = await p.chromium.launch(channel="chrome")

    的await关键字去掉就会报错

    page = await browser.new_page()

    AttributeError: 'coroutine' object has no attribute 'new_page'

    sys:1: RuntimeWarning: coroutine 'BrowserType.launch' was never awaited

    原因就是代码行 browser = p.chromium.launch(channel="chrome")还没执行完就执行了下一行 page = await browser.new_page()

    最后的总结,如果大家需要并行执行用例,那么需要考虑async (这里建议基于场景设计),如果没有这个需求,这部分只是点做为了解即可。

    我的每一篇文章都希望帮助读者解决实际工作中遇到的问题!如果文章帮到了您,劳烦点赞、收藏、转发!您的鼓励是我不断更新文章最大的动力!

    相关文章

      网友评论

          本文标题:详解async 与 await,带您理解Playwright使用

          本文链接:https://www.haomeiwen.com/subject/zwbhsdtx.html