聊聊python并发

Python提供了多线程、多进程和协程来实现并发编程。多线程适合CPU密集型任务,但需处理线程安全问题;多进程则为每个进程分配独立内存,适合资源密集型任务;协程通过asyncio模块实现轻量级并发,尤其适用于I/O密集型任务,如异步I/O操作。协程使用事件循环进行调度,避免了线程和进程的开销,提高了性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python里提供了多种方式来实现并发编程。在 Python 中,并发编程通常使用线程或进程来实现。

下面是 Python 中实现并发的几种常用方法:

  1. 使用多线程:Python 提供了内置的 threading 模块,可以用来创建和管理线程。使用多线程可以非常快地实现并发,但是需要注意线程安全问题,多线程并发示例:

    import threading
    
    def worker():  
        print("Worker thread is running")
    
    threads = []  
    for i in range(5):  
        t = threading.Thread(target=worker)  
        threads.append(t)  
        t.start()  
    

    此示例创建了五个线程,并将它们指向名为worker的函数。每个线程都打印一条消息,然后退出。在这个例子中,所有线程在同一时刻执行,因为它们都是使用同一个线程池创建的。

    多线程与多进程的区别在于,多线程共享内存,而多进程则不会。这意味着在多线程中,所有线程共享相同的变量和内存空间,因此如果有线程安全问题,则需要特别小心。在多进程中,每个进程都有自己的内存空间,因此不存在线程安全问题。

  2. 使用多进程:Python 中还可以通过创建进程来实现并发。使用多进程可以使程序更加高效,但是需要更多的内存和系统资源,多进程并发示例:

    import os  
    import processes
    
    def worker():  
        print("Worker process is running")
    
    Processes = []  
    for i in range(5):  
        p = processes.Process(target=worker)  
        Processes.append(p)  
        p.start()  
    

    在这个示例中,我们使用processes模块来创建和管理进程。此示例创建了五个进程,并将它们指向名为worker的函数。每个进程都打印一条消息,然后退出。在这个例子中,每个进程都是独立创建的,因此它们各自执行各自的任务。

    与多线程不同,多进程是创建独立的进程,每个进程都有它自己的内存空间和变量。因此,在多进程中,不需要担心线程安全问题。但是,多进程的开销较大,因为需要创建和管理新的进程。

  3. 使用协程: 协程是一种轻量级的并发机制,它不需要创建新的进程或线程,可以在单个线程中执行。协程的优势在于其高效、简洁、易于维护等优点。在 Python 中,可以使用asyncio模块来创建和管理协程。

    协程的并发机制是通过事件循环来实现的。事件循环是一个等待函数调用的循环,它不断地检查是否有事件需要处理,如果有,则将其放入事件队列中等待处理。当事件队列为空时,事件循环会进入睡眠状态,等待下一个事件到来。

    在 Python 中,协程是由asyncio模块管理的。协程的创建和使用方式与多线程和多进程类似,但在性能上却大大优于它们。协程不会占用过多的系统资源,而是只在需要时才会执行,这使得协程在处理 I/O 密集型任务时非常出色。下面是一个使用协程实现并发的例子:

    import asyncio
    
    async def worker():    
        print("Worker is running")    
        await asyncio.sleep(1)    
        print("Worker is done")
    
    async def main():    
        print("Main is running")    
        await worker()    
        print("Main is done")
    
    asyncio.run(main())  
    
    

    在这个例子中,我们定义了两个协程worker和main。协程worker会打印两条消息,然后等待 1 秒钟,最后再打印一条消息。协程main会打印一条消息,然后等待worker协程执行完成,最后再打印一条消息。
    在 Python 中,协程是由事件循环管理的,因此协程的并发执行是由事件循环来实现的。在这个例子中,事件循环会同时等待worker协程和main协程执行完成,然后一起打印最后一条消息。
    总之,使用协程可以实现高效的并发,并且不需要创建新的进程或线程。但是,由于协程是由事件循环管理的,因此需要小心处理协程的嵌套和资源的共享,以避免潜在的问题和性能问题。

  4. 当需要处理大量 I/O 操作或者需要高度并发性能时,Python 协程是一个非常有用的工具。以下是几个 Python 协程的经典用法:

  5. 异步 I/O:协程可以用于处理 I/O 密集型任务,例如从网络中读取大量数据或从磁盘中读取文件。使用协程可以大大加快 I/O 操作的执行速度,因为协程可以在后台处理任务,而不会占用主线程的资源。以下是一个简单的示例,演示如何使用协程来完成一个异步 I/O 操作:

    import asyncio  
    import aiohttp
    
    async def download_file(url, path):      
        async with aiohttp.ClientSession() as session:      
            async with session.get(url) as response:      
                async with response.headers['Content-Disposition'] as disposition:      
                    filename = f'{path}/{disposition.split(';')[0]}'      
                    async with response.open('wb') as file:      
                        file.write(response.data)      
                        return filename
    
    async def main():      
        url = 'https://example.com/data.zip'      
        path = './data.zip'      
        filename = download_file(url, path)      
        print(f'Download completed: {filename}')
    
    asyncio.run(main())  
    

    在这个示例中,我们定义了两个协程download_filemain。协程download_file会从指定 URL 下载数据,并将下载的数据保存到指定路径。协程main会启动协程download_file,并打印一条消息来表示下载已经完成。

  6. 协程嵌套:在 Python 中,协程可以嵌套执行。这意味着可以使用嵌套协程来处理复杂的任务,从而提高代码的可读性和可维护性。以下是一个简单的示例,演示如何使用嵌套协程来完成一个任务:
    import asyncio
    
    async def outer_coroutine():      
        print('Outer coroutine is running')      
        await asyncio.sleep(1)      
        print('Outer coroutine is done')    
    
    async def inner_coroutine():      
        print('Inner coroutine is running')      
        await asyncio.sleep(1)      
        print('Inner coroutine is done')    
    
    async def main():      
        print('Main is running')      
        await outer_coroutine()      
        await inner_coroutine()      
        print('Main is done')
    
    asyncio.run(main())  
    

    在这个示例中,我们定义了一个嵌套协程inner_coroutineouter_coroutine。协程outer_coroutine会打印两条消息,然后等待 1 秒钟,最后再打印一条消息。协程inner_coroutine会打印两条消息,然后等待 1 秒钟,最后再打印一条消息。

    协程的嵌套可以提高代码的可读性和可维护性,因为嵌套协程可以清晰地表示任务的逻辑和执行顺序。

  7. 协程调度:Python 协程可以使用事件循环来调度协程的执行。这意味着可以使用事件循环来决定哪些协程应该被执行,以及如何执行它们。以下是一个简单的示例,演示如何使用协程调度来完成一个任务:
    import asyncio
    
    async def worker():      
        print('Worker is running')      
        await asyncio.sleep(1)      
        print('Worker is done')
    
    async def main():      
        print('Main is running')      
        await worker()      
        print('Main is done')
    
    asyncio.run(main())  
    

    在这个示例中,我们定义了一个协程worker和一个主协程main。协程worker会打印两条消息,然后等待 1 秒钟,最后再打印一条消息。主协程main会打印一条消息来表示协程worker正在执行,然后等待协程worker执行完成,最后再打印一条消息来表示协程main已经执行完成。

总结:

       Python 中的并发模块主要有:threading, asyncio, aiohttp, async, async/await

  • threading: 传统的线程模块,提供了创建、启动和管理线程的功能。可以用于处理 CPU 密集型任务,但是线程的创建和管理较为繁琐,不适用于 I/O 密集型任务。
  • asyncio: Python 3.5 引入的协程模块,提供了一种轻量级的并发机制,可以在单个线程中处理大量的 I/O 操作,适用于处理大量 I/O 操作的任务,例如网络爬虫、文件读写等。
  • aiohttp: 一个用于处理 Web 服务的异步 I/O 库,可以用于处理 Web 请求,适用于处理大量并发请求的任务。
  • async/await: Python 3.5 引入的协程模块,提供了一种轻量级的并发机制,可以用于处理大量 I/O 操作的任务,例如网络爬虫、文件读写等。async/await 更加灵活,可以根据需要嵌套调用,适用于处理 CPU 密集型任务。

综上所述,不同的并发模块适用于不同的场景,需要根据具体情况选择合适的并发模块。同时,不同模块之间的优缺点也有所不同,需要根据具体情况进行选择。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

挪摆闪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值