本文共 5336 字,大约阅读时间需要 17 分钟。
协程(Coroutine),又称微线程或纤程,是一种用户级线程。与传统的操作系统线程不同,协程的切换和调度不是由操作系统控制的,而是由程序员自行管理。这种特性使得协程在处理I/O密集型应用时更加高效,适合需要多个入口点进行暂停和恢复的场景。
Python的协程支持起源于生成器(Generators)的出现。最初,开发者通过生成器实现了协程功能。随后,在Python 3.5版本中,async和await关键字被引入,这些语法糖大大简化了协程的书写和使用,使得协程代码更加易读和维护。如今,Python内置的asyncio标准库和诸多第三方库(如greenlet、gevent、Tornado)共同构成了现代Python协程生态系统。
Python中的协程依赖于事件循环(Event Loop)来实现异步操作。事件循环负责监听和分发事件,如网络请求、文件IO等。当协程遇到await表达式时,它会将控制权交还给事件循环,并挂起自身的执行。这样,事件循环可以继续处理其他任务,直到被挂起的协程可以继续执行时,事件循环再将控制权交回给该协程。
这种协程模型使得Python能够在不阻塞主线程的情况下,高效地执行多个异步任务,特别适合处理I/O密集型应用。
迭代是指通过for循环遍历某一系列的取值的过程。例如:
for i in [1,2,3,4,5]: print(i)
可迭代对象是指能够支持for循环操作的对象。这些对象需要实现__iter__方法。常见的可迭代对象包括列表、元组、字典、集合、range等。例如:
from collections.abc import Iterableprint(isinstance([1,2,3], Iterable)) # 输出: True
迭代器对象是指通过实现__iter__和__next__方法创建的对象。这些对象能够像生成器一样提供一系列的值。例如:
from collections.abc import Iterable, Iteratorclass Mylist(object): def __init__(self): self.mylist = [] def append_item(self, item): self.mylist.append(item) def __iter__(self): return MyIterator(self.mylist)class MyIterator(object): def __init__(self, mylist): self.mylist = mylist self.current_index = 0 def __next__(self): if self.current_index < len(self.mylist): res = self.mylist[self.current_index] self.current_index += 1 return res else: raise StopIteration# 创建可迭代对象my_list = Mylist()my_list.append_item(1)my_list.append_item(2)# 获取迭代器对象my_it = iter(my_list)print('可迭代对象:', isinstance(my_list, Iterable)) # 输出: Trueprint('迭代器对象:', isinstance(my_it, Iterator)) # 输出: True# 遍历并打印结果while True: try: value = next(my_it) print(value) except StopIteration: break 迭代器的核心功能是通过next()函数获取下一个数据值。在迭代器中,每次返回的数据值不是从一个现有的数据集合中读取,而是通过程序逻辑计算生成的。例如,生成斐波拉契数列的迭代器:
class Feibonaqie(object): def __init__(self, num): self.num = num self.a = 0 self.b = 1 self.current_index = 0 def __iter__(self): return self def __next__(self): if self.current_index < self.num: result = self.a self.a, self.b = self.b, self.a + self.b self.current_index += 1 return result else: raise StopIteration# 创建斐波拉契数列迭代器res = Feibonaqie(5)print(list(res)) # 输出: [0, 1, 1, 2, 3]
迭代器通过记录当前数据的位置,以便获取下一个位置的值,这使得它在性能敏感的场景中非常有用。
生成器(Generator)是Python的一种特殊迭代器。只要在函数定义中包含yield关键字,该函数就被称为生成器。生成器不需要像普通迭代器那样手动实现__iter__和__next__方法。
使用元组推导式:
res = (i * 2 for i in range(5))print(res) # 输出:at 0x...>print(tuple(res)) # 输出: (0, 2, 4, 6, 8)
使用yield关键字:
def coroutine_example(): while True: value = yield 0 print(f"Received value: {value}") value = yield value + 1 print(f"Received value: {value}")c = coroutine_example()print('result:', next(c)) # 输出: 0print('result2:', c.send(2)) # 输出: 3print('result4:', c.send(4)) # 输出: 0yield from:
yield from用于支持子生成器。例如:
def gen(): while True: value = yield 0 print(f"Received value: {value}") value = yield value + 1 print(f"Received value: {value}")def ren(): yield from gen()c = ren()print('result:', next(c)) # 输出: 0print('result2:', c.send(2)) # 输出: 3print('result4:', c.send(4)) # 输出: 0asyncio.coroutine:
在异步编程中,asyncio.coroutine装饰器用于标识协程函数。例如:
import timeimport asyncio@asyncio.coroutinedef taskIO_1(): print('开始运行IO任务1...') yield from asyncio.sleep(2) # 模拟耗时2秒的IO任务 print('IO任务1已完成,耗时2秒') return taskIO_1.__name__@asyncio.coroutinedef taskIO_2(): print('开始运行IO任务2...') yield from asyncio.sleep(3) # 模拟耗时3秒的IO任务 print('IO任务2已完成,耗时3秒') return taskIO_2.__name__async def main(): tasks = [taskIO_1(), taskIO_2()] done, pending = yield from asyncio.wait(tasks) for r in done: print('协程无序返回值:', r.result())if __name__ == '__main__': start = time.time() loop = asyncio.get_event_loop() try: loop.run_until_complete(main()) finally: loop.close() print('所有IO任务总耗时%.5f秒' % float(time.time() - start))异步编程通过协程实现非阻塞的并发处理。协程的执行依赖于事件循环,事件循环负责调度协程的执行。Python的async和await关键字使得协程代码更加简洁易读。
async和await的作用async def定义了一个异步函数,该函数可以使用await关键字挂起执行,等待异步任务完成。例如:
import timeimport asyncioasync def taskIO_1(): print('开始运行IO任务1...') await asyncio.sleep(3) # 模拟耗时3秒的IO任务 print('IO任务1已完成,耗时3秒') return taskIO_1.__name__async def taskIO_2(): print('开始运行IO任务2...') await asyncio.sleep(2) # 模拟耗时2秒的IO任务 print('IO任务2已完成,耗时2秒') return taskIO_2.__name__async def main(): result = await asyncio.gather(taskIO_1(), taskIO_2()) print(result)if __name__ == '__main__': start = time.time() loop = asyncio.get_event_loop() try: loop.run_until_complete(main()) finally: loop.close() print('所有IO任务总耗时%.5f秒' % float(time.time() - start)) 事件循环通过asyncio.wait()等函数等待多个任务完成,返回已完成和未完成任务的集合。如需按顺序等待任务完成,可使用asyncio.gather()函数。例如:
async def main(): result = await asyncio.gather(taskIO_1(), taskIO_2()) print(result)# 或者async def main(): tasks = [taskIO_1(), taskIO_2()] done, pending = await asyncio.wait(tasks) for r in done: print('协程无序返回值:', r.result()) 协程和生成器是Python异步编程的核心技术。协程通过事件循环实现非阻塞的任务调度,而生成器则为协程提供了一种灵活的执行方式。理解这些概念是掌握现代Python异步编程的基础。
转载地址:http://asafk.baihongyu.com/