monkey_patch(time = True)如何影响eventlet.spawn?

时间:2015-06-20 03:22:02

标签: python python-2.7 eventlet greenlets

通常,在使用greenthread时,我可以将代码编写为:

def myfun():
    print "in my func"
eventlet.spawn(myfunc)
eventlet.sleep(0)  #then myfunc() is triggered as a thread.

但在使用money_patch(time=true)后,我可以将代码更改为:

eventlet.monkey_patch(time=True)
eventlet.spawn(myfunc) # now myfunc is called immediately

为什么我这次不需要致电eventlet.sleep(0)

在我写完自己的睡眠功能后:

def my_sleep(seconds):
    print "oh, my god, my own..."

并将内置时间模块的sleep attr设置为my_sleep func,然后我发现my_sleep func将被调用很多次,输出很多。 但我只能在eclipse中看到一个调试线程,它没有调用my_sleep func。

因此,结论是,默认情况下会连续调用sleep函数,我认为eventlet的作者知道这一点,因此他们开发了monkey_patch()函数。那是不是很严格?

根据@temoto的回答,CPython无法重现相同的结果。我认为我应该添加一些信息来介绍我如何找到这个有趣的东西。(为什么我第一次没有添加这个消息,导致输入这么多单词并不容易,而且我的英语不太好。^^)

当我使用eclipse远程调试openstack代码时,我发现了这一点。

在nova / network / model.py中,函数编写如下:

class NetworkInfoAsyncWrapper(NetworkInfo):
    """Wrapper around NetworkInfo that allows retrieving NetworkInfo
    in an async manner.

    This allows one to start querying for network information before
    you know you will need it.  If you have a long-running
    operation, this allows the network model retrieval to occur in the
    background.  When you need the data, it will ensure the async
    operation has completed.

    As an example:

    def allocate_net_info(arg1, arg2)
        return call_neutron_to_allocate(arg1, arg2)

    network_info = NetworkInfoAsyncWrapper(allocate_net_info, arg1, arg2)
    [do a long running operation -- real network_info will be retrieved
    in the background]
    [do something with network_info]
    """

    def __init__(self, async_method, *args, **kwargs):
        self._gt = eventlet.spawn(async_method, *args, **kwargs)
        methods = ['json', 'fixed_ips', 'floating_ips']
        for method in methods:
            fn = getattr(self, method)
            wrapper = functools.partial(self._sync_wrapper, fn)
            functools.update_wrapper(wrapper, fn)
            setattr(self, method, wrapper)

当我第一次调试到这个函数时,执行后

  

self._gt = eventlet.spawn(async_method,* args,** kwargs)

回拨函数async_method立即执行。但请记住,这是一个帖子,它应该由eventlet.sleep(0)触发。

但是我没有找到调用sleep(0)的代码,所以如果sleep可能被eclipse调用,那么在现实世界(非调试世界)中,是谁触发了它?

1 个答案:

答案 0 :(得分:1)

TL; DR:Eventlet API不需要sleep(0)来启动绿色线程。 spawn(fun)将在未来的某个时间开始运作,包括现在。您只应致电sleep(0) 确保立即启动,即使这样,最好使用显式同步,例如EventSemaphore

我无法在IPython或纯python控制台中使用CPython 2.7.6和3.4.3,eventlet 0.17.4重现此行为。所以可能是Eclipse在后台调用time.sleep

引入了

monkey_patch作为运行所有(和第三方)代码并替换time.sleep -> eventlet.sleep的快捷方式,以及类似于ossocket等模块的快捷方式。它与Eclipse(或其他)重复time.sleep次呼叫无关。

但这是一个有趣的观察,谢谢。