python协程

本文介绍了协程的基本概念,包括其作为轻量级并发方式的特点,以及通过yield关键字、async/await语法、asyncio库和gevent/greenlet库实现的示例。重点讲解了协程调度、异步操作和线程安全问题。
1、协程的概念

协程是一种轻量级的并发编程方式,又称微线程,纤程;其本质就是线程。可以将一个任务划分为多个子任务,使得任务的切换和执行更加高效和灵活,由用户程序自己控制调度的。协程的本质是一种特殊的函数,它与普通函数的区别在于,可以在函数执行过程中暂停执行,将控制权交还给调用者,待稍后再恢复执行。

2、协程通过 yield 关键字实现
def test1():
	yield 'begin'
	yield from test2
	yield 'end'
def test2():
	yield 'aaa'
	yield 'bbb'
t1 = test1()
for i in t1:
  print(i)
"""
begin
aaa
bbb
end
"""

3、通过async/await语法进行实现。asyncio提供了一个事件循环(event loop),通过它可以实现协程的调度和执行。

关于async方法,在另一篇转载的文章(python 协程asyncio详解),有其他方面的用法,可以查看
下面是一个简单的协程示例:

import asyncio

async def hello():
    print("Hello")
    await asyncio.sleep(1)  # 模拟一个耗时操作
    print("World")

async def main():
    await asyncio.gather(hello(), hello(), hello())

asyncio.run(main())

输出结果为:

Hello
Hello
Hello
World
World
World

在上面的示例中,hello函数是一个协程函数,它在执行过程中使用了await asyncio.sleep(1)语句将执行暂停了1秒钟。在main函数中,使用asyncio.gather方法并发执行了三个hello协程。

需要注意的是,协程调用时并不会立即执行,而是会返回一个协程对象。协程的执行必须在事件循环中进行。

协程的优点在于,它们可以在不需要多线程或多进程的情况下实现并发,并且更加轻量级和高效。但是,需要注意协程中的线程安全问题,例如共享数据访问需要进行加锁操作。

4、通过gevent实现协程

gevent是一个基于libev的使用协程实现并发的Python库。它的核心是一个事件循环,能够利用操作系统提供的异步I/O机制(如epoll,kqueue和libevent)来实现高性能的异步I/O操作和并发任务处理。

gevent的协程是基于greenlet实现的,使用它可以实现纯Python的协程,并且不需要显式的编写回调函数,代码可读性更好。下面是一个简单的gevent协程实现:

import gevent

def task(pid):
    """
    Some non-deterministic task
    """
    gevent.sleep(0.5)
    print('Task %s done' % pid)

def synchronous():
    for i in range(1, 10):
        task(i)

def asynchronous():
    threads = [gevent.spawn(task, i) for i in range(1, 10)]
    gevent.joinall(threads)

print('Synchronous:')
synchronous()

print('Asynchronous:')
asynchronous()

在这个例子中,我们定义了一个task函数,它利用gevent提供的sleep函数来模拟一个非确定性任务。在synchronous函数中,我们使用for循环来顺序执行这个任务,而在asynchronous函数中,我们创建了9个协程来并发执行这个任务。

最后,我们调用synchronous和asynchronous函数来测试它们的执行效果。可以看到,asynchronous函数的执行速度明显比synchronous函数快,这是因为它使用了gevent提供的异步I/O和协程并发机制。

除了基本的协程机制外,gevent还提供了一些高级特性,如信号处理、异步DNS解析、线程池和进程池等,可以更方便地实现一些高级的并发任务处理。

5、通过greenlet实现协程(此方法是落后版本,gevent是高级版本,此方法可不看)

greenlet是一个轻量级的Python库,可以实现协程。它提供了一个Greenlet类,可以在同一个线程中执行不同的代码块,从而模拟出协程的效果。下面是一个使用greenlet实现协程的例子:

import greenlet

def func1():
    print("start func1")
    gr2.switch()
    print("end func1")
    
def func2():
    print("start func2")
    gr1.switch()
    print("end func2")
    
gr1 = greenlet.greenlet(func1)
gr2 = greenlet.greenlet(func2)

gr1.switch() #启动协程

在上面的例子中,我们定义了两个函数func1和func2,每个函数中都有一个switch语句,用于切换到另一个协程。我们创建了两个Greenlet对象gr1和gr2,分别绑定到func1和func2函数上。

在最后一行代码中,我们使用gr1.switch()启动了第一个协程。程序先执行func1函数,打印出"start func1",然后调用gr2.switch()将执行权交给了func2函数,打印出"start func2",然后再次调用gr1.switch()将执行权交回给了func1函数,打印出"end func1",最后程序结束。

通过greenlet实现协程,可以避免使用线程或进程带来的开销,提高程序的性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值