飞道的博客

python协程——多任务的实现

305人阅读  评论(0)

1、使用yield完成多任务

实例

import time
def task_1():
    while True:
        print('----1----')
        time.sleep(0.1)
        yield
        

def task_2():
    while True:
        print('----2----')
        time.sleep(0.2)
        yield

def main():
    t1 = task_1()
    t2 = task_2()
    while True:
        next(t1)
        next(t2)

if __name__ == '__main__':
    main()

运行结果

----1----
----2----
----1----
----2----
----1----
----2----
----1----
----2----
----1----
----2----
----1----
----2----

可以看到,我们已经成功的完成了多任务,一直在交替执行两个函数,这里的执行是并发,是一个假的多任务。

2、使用greenlet完成多任务

为了更好地使用协程来完成多任务,python中的greenlet模块对其封装,从而使得切换任务变得更加简单。

安装方式

pip3 install greenlet

使用

from greenlet import greenlet
import time


def test1():
    while True:
        print('----A----')
        gr2.switch()
        time.sleep(0.5)

def test2():
    while True:
        print('----B----')
        gr1.switch()
        time.sleep(0.5)

gr1 = greenlet(test1)
gr2 = greenlet(test2)

# 切换到gr1中运行
gr1.switch()

运行效果:

----A----
----B----
----A----
----B----
----A----
----B----
----A----
----B----

他实现的原理就是两个函数交替执行,每次各执行一下,就达到了多任务的目的

3、使用gevent完成多任务

安装

pip3 install gevent

实例

import gevent
import time

def f1(n):
    for i in range(n):
        print(gevent.getcurrent(), i)
        gevent.sleep(0.5)

def f2(n):
    for i in range(n):
        print(gevent.getcurrent(), i)
        gevent.sleep(0.5)

def f3(n):
    for i in range(n):
        print(gevent.getcurrent(), i)
        gevent.sleep(0.5)

if __name__ == '__main__':
    print('-----1-----')
    g1 = gevent.spawn(f1, 5)
    print('-----2-----')
    g2 = gevent.spawn(f2, 5)
    print('-----3-----')
    g3 = gevent.spawn(f3, 5)
    print('-----4-----')

    g1.join()
    g2.join()
    g3.join()

运行结果

-----1-----
-----2-----
-----3-----
-----4-----
<Greenlet at 0x1cf52eb2948: f1(5)> 0
<Greenlet at 0x1cf52eb2c48: f2(5)> 0
<Greenlet at 0x1cf52eb2d48: f3(5)> 0
<Greenlet at 0x1cf52eb2948: f1(5)> 1
<Greenlet at 0x1cf52eb2c48: f2(5)> 1
<Greenlet at 0x1cf52eb2d48: f3(5)> 1
<Greenlet at 0x1cf52eb2948: f1(5)> 2
<Greenlet at 0x1cf52eb2c48: f2(5)> 2
<Greenlet at 0x1cf52eb2d48: f3(5)> 2
<Greenlet at 0x1cf52eb2948: f1(5)> 3
<Greenlet at 0x1cf52eb2c48: f2(5)> 3
<Greenlet at 0x1cf52eb2d48: f3(5)> 3
<Greenlet at 0x1cf52eb2948: f1(5)> 4
<Greenlet at 0x1cf52eb2c48: f2(5)> 4
<Greenlet at 0x1cf52eb2d48: f3(5)> 4

可以看到,他是三个函数交替运行,实现了多任务的功能。
注意:gevent函数实现多任务的原理是通过延时来实现的,利用延时将这个函数先搁置起来,用这个时间去处理其他函数。这里的延时是其自身封装好的方法。即gevent.sleep().

协程依赖于线程,线程依赖于进程。

给代码打补丁

这里注意到,我们在对·gevent的使用中的延时程序使用的是gevent.sleep()而不是平常使用的time.sleep()。如果我们现在面临一个非常庞大的代码,里面有大量的time.sleep()我们需要对他使用gevent进行构造的话,如果重构,会造成非常大的麻烦。
可以在代码前面添加

from gevent import monkey
monkey.patch_all()

实例:

from gevent import monkey
import gevent
import time
import random
monkey.patch_all()

def coroutine_work(coroutine_name):
    for i in range(10):
        print(coroutine_name, i)
        time.sleep(random.random())


if __name__ == '__main__':
    # 如果我们执行多任务的数量非常多时,为了避免写非常多的g1.join()
    # 这里为我们提供了一种列表的方法.   gevent.spawn(目标函数, 参数)
    gevent.joinall([
        gevent.spawn(coroutine_work, "work1"),
        gevent.spawn(coroutine_work, "work2")
    ])

运行结果:

```work1 0
work2 0
work1 1
work2 1
work1 2
work1 3
work2 2
work1 4
work2 3
work2 4
work1 5
work2 5
work1 6
work2 6
work1 7
work1 8

可以看到他成功的实现了多任务。

转载:https://blog.csdn.net/weixin_42137701/article/details/105536694
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场