2

通常,在使用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..."

并将内置时间模块的睡眠属性设置为my_sleepfunc,然后我发现my_sleepfunc会被调用很多次,输出很多。但是我在eclipse中只能看到一个调试线程,它没有调用my_sleepfunc。

所以,结论是,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调用,那么在现实世界(非调试世界)中,是谁触发了它?

4

1 回答 1

1

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

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

monkey_patch被引入作为运行所有(和第三方)代码并替换time.sleep -> eventlet.sleep, 和类似 for os,socket等模块的快捷方式。它与 Eclipse(或其他)重复time.sleep调用无关。

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

于 2015-06-20T16:03:46.193 回答