浅谈Python协程
什么是协程
协程是一种非常轻量级的线程,也称为微线程或者用户空间线程。协程与线程不同的是,线程由操作系统进行调度,而协程是程序员自行调度,因此切换的代价更低。
协程中包含多个协程对象,每个协程对象都应该包含一个状态机,也就是说,协程只有在切换时才会保存和恢复状态。
Python中的协程是通过asyncio
库来实现的,asyncio
是Python3.4中引入的标准库,提供了一种写异步代码的方案。
协程的优势
协程的优势主要在于以下几点:
- 更加高效的切换。协程的切换是用户空间的,避免了系统调用和上下文切换等开销。
- 更加轻量级的线程。线程的启动和销毁需要开销很大的系统调用,而协程的启动和销毁只需要简单的对象构造和析构操作。
- 更好的可读性和可维护性。协程的代码结构更加清晰,没有锁和同步的问题,代码可读性和可维护性都更高。
如何使用协程
Python中使用协程需要用到async
和await
这两个关键字。
async
关键字用于定义一个协程函数,表示这个函数是一个异步函数,可以使用await
来进行挂起。
await
关键字用于挂起一个协程,直到协程内部的异步操作执行完成。
下面是一个使用协程的示例代码:
import asyncio
async def hello():
print('Hello')
await asyncio.sleep(1)
print('World')
async def main():
tasks = [hello(), hello()]
await asyncio.gather(*tasks)
if __name__ == '__main__':
asyncio.run(main())
这段代码中,hello
函数是一个协程函数,它包含了一个异步操作asyncio.sleep
,表示等待1秒后再继续执行后续代码。
main
函数也是一个协程函数,它调用了两个hello
函数,并使用asyncio.gather
等待所有任务执行完毕。
运行以上代码可以看到输出结果为:
Hello
Hello
World
World
协程的应用场景
协程的应用场景非常广泛,常见的应用场景包括:
- 服务器中的网络编程,协程可以代替传统的多线程编程模型,提高并发性能。
- I/O密集型任务,例如文件读写、网络通信等,使用协程可以避免I/O等待时的大量资源浪费。
- CPU密集型任务,例如加密、解密、图像处理等,虽然协程无法真正地并行执行,但是使用协程可以提高CPU利用率,避免阻塞等待。
示例
下面我们来看一个使用协程进行爬虫的示例代码:
import asyncio
import aiohttp
async def get(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
url_list = [
'https://www.baidu.com',
'https://www.jd.com',
'https://www.taobao.com',
]
tasks = []
for url in url_list:
tasks.append(asyncio.create_task(get(url)))
for task in asyncio.as_completed(tasks):
result = await task
print(f'URL: {result[:20]}')
if __name__ == '__main__':
asyncio.run(main())
在这个示例代码中,我们定义了一个get
函数,用于通过aiohttp
模块发起HTTP GET请求,并返回响应内容。
main
函数中创建了三个URL的列表,并通过循环创建相应的协程任务。使用asyncio.as_completed
函数等待所有任务完成,并获取结果,然后输出结果的前20个字节。
运行以上代码可以看到输出结果为:
URL: <html><head><meta http
URL: <!DOCTYPE html>\n<htm
URL: <!DOCTYPE html>\n<htm
可以看到,我们成功通过协程并发地发起了三个HTTP GET请求,并获取了相应的响应数据。
总结
协程是一种轻量级的线程,使用Python的asyncio
库可以很方便地实现协程。协程的优势在于更高的执行效率和更好的可读性和可维护性。协程的应用场景包括服务器中的网络编程、I/O密集型任务、CPU密集型任务等。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈Python协程 - Python技术站