Python协程

文章介绍了Python中实现多任务的几种方式,包括使用yield、greenlet和gevent库。通过示例展示了如何通过这些方法进行上下文切换,实现并发执行。特别是gevent,它能自动处理耗时操作,提高程序效率。
摘要由CSDN通过智能技术生成

理论

        python中多任务的实现可以使用进程、线程或协程。

        协程是单线程下的并发,又称微线程、纤程,比线程更小,占用更小的执行单元。

        协程是用户程序自己控制调度的,在计算机层面并没有协程,而是程序员根据代码实现的CPU的切换。

实践

1、yield实现上下文切换

import time


def job1():
    for i in range(4):
        print('--------job1-------', time.time() - start)
        yield
        time.sleep(1)


def job2():
    for i in range(4):
        print('--------job2-------', time.time() - start)
        yield
        time.sleep(1)


if __name__ == '__main__':
    start = time.time()
    j1 = job1()
    j2 = job2()
    for i in range(3):
        next(j1)
        next(j2)
    print(time.time() - start)

运行结果

--------job1------- 4.0531158447265625e-06
--------job2------- 4.601478576660156e-05
--------job1------- 1.0011780261993408
--------job2------- 2.001481056213379
--------job1------- 3.00597882270813
--------job2------- 4.011059045791626
4.011122941970825

2、greenlet实现上下文切换

import greenlet
import time


def job1():
    for i in range(3):
        print('--------job1-------', time.time() - start)
        j2.switch()
        time.sleep(1)


def job2():
    for i in range(3):
        print('--------job2-------', time.time() - start)
        j1.switch()
        time.sleep(1)


if __name__ == '__main__':
    start = time.time()
    j1 = greenlet.greenlet(job1)
    j2 = greenlet.greenlet(job2)
    j1.switch()
    print(time.time() - start)

运行结果

--------job1------- 1.0013580322265625e-05
--------job2------- 5.1975250244140625e-05
--------job1------- 1.0030829906463623
--------job2------- 2.0068538188934326
--------job1------- 3.0111947059631348
--------job2------- 4.015782833099365
5.018911838531494

3、gevent实现协程

       在上面的代码中,yield和greenlet仅实现代码上下文的切换,还算不上协程。

       在下面的代码中,使用gevent.sleep()代替time.sleep()模拟耗时操作,原因是在程序中有耗时操作时,需要将耗时操作代码替换为gevent中自己实现的代码,才能自动切换协程。 

import gevent
import time


def job1():
    for i in range(3):
        print('--------job1-------', time.time() - start)
        gevent.sleep(1)


def job2():
    for i in range(3):
        print('--------job2-------', time.time() - start)
        gevent.sleep(1)


if __name__ == '__main__':
    start = time.time()
    j1 = gevent.spawn(job1, )
    j2 = gevent.spawn(job2, )
    gevent.joinall([j1, j2])
    print(time.time() - start)

 运行结果

--------job1------- 0.0005421638488769531
--------job2------- 0.0006239414215087891
--------job1------- 1.0010240077972412
--------job2------- 1.001089096069336
--------job1------- 2.003490924835205
--------job2------- 2.0035531520843506
3.0075089931488037

4、gevent+猴子补丁实现协程

         在实际开发中,将会面对许多复杂的情况,我们实现协程时尽量不去修改原有的代码,所以gevent模块中提供了一个猴子补丁,帮开发人员实现自动将耗时代码替换成gevent自己实现的模块。

import gevent
from gevent import monkey
import time

monkey.patch_all()


def job(a):
    for i in range(3):
        print(f'--------job{a}-------', time.time() - start)
        time.sleep(1)


if __name__ == '__main__':
    start = time.time()
    j1 = gevent.spawn(job, 1)
    j2 = gevent.spawn(job, 2)
    gevent.joinall([j1, j2])
    print(time.time() - start)

运行结果

--------job1------- 0.00033593177795410156
--------job2------- 0.00041413307189941406
--------job1------- 1.0042319297790527
--------job2------- 1.004328966140747
--------job1------- 2.00445818901062
--------job2------- 2.004521131515503
3.006899118423462

参考内容:介绍 — gevent 21.8.0 文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值