快乐学习
前程无忧、中华英才非你莫属!

Python-异步编程-gevent-5

猴子补丁

唉,我们来到了 Gevent 的黑暗角落。到目前为止,我一直避免提及猴子补丁以尝试激发强大的协程模式,但现在是讨论猴子补丁的黑暗艺术的时候了。如果你注意到上面我们调用了命令 monkey.patch_socket()。这是一个纯粹的副作用命令,用于修改标准库的套接字库。

import socket
print(socket.socket)

print("After monkey patch")
from gevent import monkey
monkey.patch_socket()
print(socket.socket)

import select
print(select.select)
monkey.patch_select()
print("After monkey patch")
print(select.select)

class 'socket.socket'
After monkey patch
class 'gevent.socket.socket'

built-in function select
After monkey patch
function select at 0x1924de8

Python 的运行时允许在运行时修改大多数对象,包括模块、类甚至函数。这通常是一个非常糟糕的主意,因为它会产生“隐式副作用”,如果出现问题,通常很难调试,但在极端情况下,库需要改变 Python 本身的基本行为,可以使用猴子补丁. 在这种情况下,gevent 能够修补标准库中的大多数阻塞系统调用,包括在、和 模块中的那些socket,以代替合作行为。sslthreadingselect

例如,Redis python 绑定通常使用常规 tcp 套接字与redis-server实例进行通信。只需通过调用,gevent.monkey.patch_all()我们就可以使 redis 绑定调度请求协同工作,并与我们的 gevent 堆栈的其余部分一起工作。

这让我们无需编写一行代码就可以集成通常无法与 gevent 一起使用的库。虽然猴子补丁仍然是邪恶的,但在这种情况下,它是一个“有用的邪恶”。

事件异步通信

事件是 Greenlets 之间异步通信的一种形式。

import gevent
from gevent.event import Event

'''
说明事件的使用
'''

evt = Event()

def setter():
    """3 秒后,唤醒所有等待 evt 值的线程"""
    print('A: Hey wait for me, I have to do something')
    gevent.sleep(3)
    print("Ok, I'm done")
    evt.set()

def waiter():
    """3 秒后,get 调用将解除阻塞"""
    print("I'll wait for you")
    evt.wait()  # 阻塞
    print("It's about time")

def main():
    gevent.joinall([
        gevent.spawn(setter),
        gevent.spawn(waiter),
        gevent.spawn(waiter),
        gevent.spawn(waiter),
        gevent.spawn(waiter),
        gevent.spawn(waiter)
    ])

if __name__ == '__main__':
    main()

'''
A: Hey wait for me, I have to do something
I'll wait for you
I'll wait for you
I'll wait for you
I'll wait for you
I'll wait for you
Ok, I'm done
It's about time
It's about time
It's about time
It's about time
It's about time

Process finished with exit code 0

'''

Event 对象的扩展是 AsyncResult,它允许您随唤醒调用一起发送值。这有时被称为未来或延期,因为它持有对可以在任意时间安排上设置的未来值的引用


import gevent
from gevent.event import AsyncResult

a = AsyncResult()

def setter():
    """
    3 秒后设置结果
    """
    gevent.sleep(3)
    a.set('Hello!')

def waiter():
    """
    3 秒后,get 调用将在 setter 之后解除阻塞
    将一个值放入 AsyncResult.
    """
    print(a.get())

gevent.joinall([
    gevent.spawn(setter),
    gevent.spawn(waiter),
])

3秒之后,把值传给watier函数,waiter函数,通过get函数获取hello.

打赏

未经允许不得转载:同乐学堂 » Python-异步编程-gevent-5

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

特别的技术,给特别的你!

联系QQ:1071235258QQ群:367203382
error: Sorry,暂时内容不可复制!