美文网首页
《Python 核心技术与实战》 学习笔记 Day21 并发编程

《Python 核心技术与实战》 学习笔记 Day21 并发编程

作者: _相信自己_ | 来源:发表于2023-02-04 16:34 被阅读0次

    什么是 Asyncio

    首先来区分一下 Sync(同步)和 Async(异步)的概念。

    • 所谓 Sync,是指操作一个接一个地执行,下一个操作必须等上一个操作完成后才能执行。而 - Async 是指不同操作间可以相互交替执行,如果其中的某个操作被 block 了,程序并不会等待,而是会找出可执行的操作继续执行。
      举个简单的例子,你的老板让你做一份这个季度的报表,并且邮件发给他。
    • 如果按照 Sync 的方式,你会先向软件输入这个季度的各项数据,接下来等待 5min,等报表明细生成后,再写邮件发给他。
    • 但如果按照 Async 的方式,再你输完这个季度的各项数据后,便会开始写邮件。等报表明细生成后,你会暂停邮件,先去查看报表,确认后继续写邮件直到发送完毕。

    Asyncio 工作原理

    事实上,Asyncio 和其他 Python 程序一样,是单线程的,它只有一个主线程,但是可以进行多个不同的任务(task),这里的任务,就是特殊的 future 对象。这些不同的任务,被一个叫做 event loop 的对象所控制。你可以把这里的任务,类比成多线程版本里的多个线程。

    Asyncio 用法

    
    import asyncio
    import aiohttp
    import time
    
    async def download_one(url):
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                print('Read {} from {}'.format(resp.content_length, url))
    
    async def download_all(sites):
        tasks = [asyncio.create_task(download_one(site)) for site in sites]
        await asyncio.gather(*tasks)
    
    def main():
        sites = [
            'https://en.wikipedia.org/wiki/Portal:Arts',
            'https://en.wikipedia.org/wiki/Portal:History',
            'https://en.wikipedia.org/wiki/Portal:Society',
            'https://en.wikipedia.org/wiki/Portal:Biography',
            'https://en.wikipedia.org/wiki/Portal:Mathematics',
            'https://en.wikipedia.org/wiki/Portal:Technology',
            'https://en.wikipedia.org/wiki/Portal:Geography',
            'https://en.wikipedia.org/wiki/Portal:Science',
            'https://en.wikipedia.org/wiki/Computer_science',
            'https://en.wikipedia.org/wiki/Python_(programming_language)',
            'https://en.wikipedia.org/wiki/Java_(programming_language)',
            'https://en.wikipedia.org/wiki/PHP',
            'https://en.wikipedia.org/wiki/Node.js',
            'https://en.wikipedia.org/wiki/The_C_Programming_Language',
            'https://en.wikipedia.org/wiki/Go_(programming_language)'
        ]
        start_time = time.perf_counter()
        asyncio.run(download_all(sites))
        end_time = time.perf_counter()
        print('Download {} sites in {} seconds'.format(len(sites), end_time - start_time))
        
    if __name__ == '__main__':
        main()
    
    ## 输出
    Read 63153 from https://en.wikipedia.org/wiki/Java_(programming_language)
    Read 31461 from https://en.wikipedia.org/wiki/Portal:Society
    Read 23965 from https://en.wikipedia.org/wiki/Portal:Biography
    Read 36312 from https://en.wikipedia.org/wiki/Portal:History
    Read 25203 from https://en.wikipedia.org/wiki/Portal:Arts
    Read 15160 from https://en.wikipedia.org/wiki/The_C_Programming_Language
    Read 28749 from https://en.wikipedia.org/wiki/Portal:Mathematics
    Read 29587 from https://en.wikipedia.org/wiki/Portal:Technology
    Read 79318 from https://en.wikipedia.org/wiki/PHP
    Read 30298 from https://en.wikipedia.org/wiki/Portal:Geography
    Read 73914 from https://en.wikipedia.org/wiki/Python_(programming_language)
    Read 62218 from https://en.wikipedia.org/wiki/Go_(programming_language)
    Read 22318 from https://en.wikipedia.org/wiki/Portal:Science
    Read 36800 from https://en.wikipedia.org/wiki/Node.js
    Read 67028 from https://en.wikipedia.org/wiki/Computer_science
    Download 15 sites in 0.062144195078872144 seconds
    

    这里的 Async 和 await 关键字是 Asyncio 的最新写法,表示这个语句 / 函数是 non-block 的,正好对应前面所讲的 event loop 的概念。如果任务执行的过程需要等待,则将其放入等待状态的列表中,然后继续执行预备状态列表里的任务。

    多线程还是 Asyncio

    总的来说,你可以遵循以下伪代码的规范:

    
    if io_bound:
        if io_slow:
            print('Use Asyncio')
        else:
            print('Use multi-threading')
    else if cpu_bound:
        print('Use multi-processing')
    
    • 如果是 I/O bound,并且 I/O 操作很慢,需要很多任务 / 线程协同实现,那么使用 Asyncio 更合适。
    • 如果是 I/O bound,但是 I/O 操作很快,只需要有限数量的任务 / 线程,那么使用多线程就可以了。
    • 如果是 CPU bound,则需要使用多进程来提高程序运行效率。

    相关文章

      网友评论

          本文标题:《Python 核心技术与实战》 学习笔记 Day21 并发编程

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