通常,在使用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_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调用,那么在现实世界(非调试世界)中,是谁触发了它?