在看 nameko 的源码的时候,经常看到 gt.link(self._handle_thread_exited) 的用法

def spawn_managed_thread(self, run_method):
    """ Spawn a lifecycle-managed thread, which calls the ``run_method``
    once it has been started.

    Any errors raised inside the ``run_method`` cause the container to be
    killed.

    It is the entrypoint provider's responsibility to react to ``stop()``
    calls and terminate it's spawned threads.

    Threads are killed automatically by the container if they are
    still running after all their providers have been stopped.

    Entrypoints may only create separate threads using this method,
    to ensure they are life-cycle managed.
    """
    gt = eventlet.spawn(run_method)
    self._active_threads.add(gt)
    gt.link(self._handle_thread_exited)
    return gt

eventlet 的文档中,并没有描述这个 api 是干嘛的,所以我看了一下 eventlet 源码,其中有关于他的注释:

def link(self, func, *curried_args, **curried_kwargs):
    """ Set up a function to be called with the results of the GreenThread.

    The function must have the following signature::

        def func(gt, [curried args/kwargs]):

    When the GreenThread finishes its run, it calls *func* with itself
    and with the `curried arguments <http://en.wikipedia.org/wiki/Currying>`_ supplied
    at link-time.  If the function wants to retrieve the result of the GreenThread,
    it should call wait() on its first argument.

    Note that *func* is called within execution context of
    the GreenThread, so it is possible to interfere with other linked
    functions by doing things like switching explicitly to another
    greenthread.
    """
    if self._exit_funcs is None:
        self._exit_funcs = deque()
    self._exit_funcs.append((func, curried_args, curried_kwargs))
    if self._exit_event.ready():
        self._resolve_links()

英文是看不懂的,就用翻译软件翻译一下吧:

图片.png

原文:

Set up a function to be called with the results of the GreenThread.

        The function must have the following signature::

            def func(gt, [curried args/kwargs]):

        When the GreenThread finishes its run, it calls *func* with itself and with the `curried arguments <http://en.wikipedia.org/wiki/Currying>`_ supplied at link-time.  If the function wants to retrieve the result of the GreenThread,it should call wait() on its first argument.

        Note that *func* is called within execution context of the GreenThread, so it is possible to interfere with other linked functions by doing things like switching explicitly to another greenthread.

译文:

设置一个函数,用GreenThread的结果来调用。

        该函数必须有以下签名:。

            def func(gt, [curried args/kwargs])。

        当GreenThread完成其运行时,它用自己和在链接时提供的`curried arguments <http://en.wikipedia.org/wiki/Currying>`_调用*func*。 如果该函数想获取GreenThread的结果,它应该在其第一个参数上调用wait()。

        请注意,*func*是在GreenThread的执行上下文中调用的,所以有可能会干扰到其他链接的函数,比如明确地切换到另一个Greenthread。

所以,这 link 是干啥的?其实就是一个回调函数注册器

类似 threading 里面的 add_done_callback
具体可参考:Python 的线程池的回调函数是在主线程还是工作线程中运行的?
import eventlet
from loguru import logger


def func():
    logger.debug('执行 func')


def call_back_func(gt):
    logger.debug('执行 回调函数')


t1 = eventlet.spawn(func)
t2 = eventlet.spawn(func)
t3 = eventlet.spawn(func)

t1.link(call_back_func)
t2.link(call_back_func)
t3.link(call_back_func)

t1.wait()
t2.wait()
t3.wait()

执行结果

2022-09-04 12:58:46.889 | DEBUG    | __main__:func:6 - 执行 func
2022-09-04 12:58:46.889 | DEBUG    | __main__:call_back_func:10 - 执行 回调函数
2022-09-04 12:58:46.889 | DEBUG    | __main__:func:6 - 执行 func
2022-09-04 12:58:46.889 | DEBUG    | __main__:call_back_func:10 - 执行 回调函数
2022-09-04 12:58:46.889 | DEBUG    | __main__:func:6 - 执行 func
2022-09-04 12:58:46.889 | DEBUG    | __main__:call_back_func:10 - 执行 回调函数

universe_king
3.4k 声望678 粉丝