Python的协程

前言

在现代编程中,并发编程变得越来越重要。为了更有效地利用计算资源和提高程序的响应速度,开发者们需要掌握各种并发编程技术。Python 作为一门广泛使用的编程语言,自然也提供了多种并发编程的方法,其中协程(coroutines)是一个非常强大且灵活的工具。

什么是协程

协程是一种比线程更加轻量级的并发编程方式,它允许函数在执行过程中暂停并恢复,从而使得多个任务可以交替进行。与线程不同的是,协程的切换完全由程序控制,不依赖操作系统的调度,也就是说,线程是操作系统来调度,而协程完全是在程序中自己控制,线程在内核态完成,然后把信息同步给用户态,协程完全是在用户态。因此可以避免许多由线程切换带来的开销和问题。
在Python中,有经典协程原生协程,经典协程由生成器实现,原生协程使用async,await现代语言语法,本文只讨论原生协程(注:原生协程底层实现也是生成器

协程的有点

  • 高效利用资源:协程不会像线程那样频繁地切换上下文,因此能够更高效地利用 CPU 资源。
  • 简化代码:协程使得异步编程变得更加直观,代码的可读性和维护性得到了极大的提高。
  • 减少锁的使用:由于协程是单线程运行的,不需要像多线程那样频繁地使用锁,从而避免了许多潜在的死锁问题。

协程的使用

Python中,可以使用asyncio库莱使用协程。

import asyncio
from datetime import datetime

async def say_helle():
    await asyncio.sleep(1)
    print(f'协程')
    
async def main():
    task1 = asyncio.create_task(say_helle())
    task2 = asyncio.create_task(say_helle())
    await task1
    await task2
    
if __name__ == '__main__':
    cur = datetime.now()
    asyncio.run(main())
    print((datetime.now() - cur).total_seconds())

如果你运行代码,你会发现最后间隔时间是1s多一个,也就是说main()函数中执行了两次say_hello(),但没有阻塞2s,task2在task1没有执行完成,就开始执行了,两者都是异步的。

下面写一个简单的爬虫应用,爬取大乐透历史中奖信息

import asyncio
from datetime import datetime
import aiohttp

async def fetch(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()
        
        
async def main():
    urls = []
    for i in range(1,20):
        url = f'https://webapi.sporttery.cn/gateway/lottery/getHistoryPageListV1.qry?gameNo=85&provinceId=0&pageSize=30&isVerify=1&pageNo={i}'
        urls.append(url)
        
    tasks = [asyncio.create_task(fetch(url)) for url in urls]
    results = await asyncio.gather(*tasks)
    for result in results:
        print(result)
        
if __name__ == '__main__':
    asyncio.run(main())

你们自己可以对比一下使用协程和使用同步请求的速度。

注意事项

  • 避免阻塞操作:协程的优势在于非阻塞,如果在协程中使用了阻塞操作,会导致整个事件循环被阻塞,从而失去协程的优势。
  • 错误处理:协程中的错误需要使用 try…except 进行捕获,并在合适的地方处理。
  • 资源管理:确保正确地管理资源,如网络连接、文件句柄等,使用 async with 可以帮助你更好地管理资源。

总结

Python 的协程提供了一种高效、简洁的并发编程方式。通过 asyncio 库,你可以轻松地编写出高性能的异步程序。虽然协程的概念和用法需要一些学习成本,但一旦掌握,你会发现它在许多场景下是不可或缺的利器。协程有时候被叫做“轻量级线程”,具体轻量在哪呢?我觉得协程和线程最本质区别就是线程由操作系统调度,而协程是代码中调度,不需要经过操作系统,也就是内核态,所以协程也比线程更容易管理。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值