Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么python gevent.joinall会执行所有greenlet_Python_Gevent_Greenlets - Fatal编程技术网

为什么python gevent.joinall会执行所有greenlet

为什么python gevent.joinall会执行所有greenlet,python,gevent,greenlets,Python,Gevent,Greenlets,我有以下Python代码: >>> import gevent >>> from gevent import monkey; monkey.patch_all() >>> >>> def fooFn(k): ... return 'gevent_'+k ... >>> threads = [] >>> threads.append(gevent.spawn(fooFn,'0'))

我有以下Python代码:

>>> import gevent
>>> from gevent import monkey; monkey.patch_all()
>>>
>>> def fooFn(k):
...     return 'gevent_'+k
...
>>> threads = []
>>> threads.append(gevent.spawn(fooFn,'0'))
>>> threads.append(gevent.spawn(fooFn,'1'))
>>>
>>> gevent.joinall([threads[1]])
>>>
>>> print threads[1].value
gevent_1
>>> print threads[0].value
gevent_0
>>>
如上所示,
threads[0]。value
fooFn
获取了一个正确的值。这意味着执行了
线程[0]
greenlet

当我只将
线程[1]
greenlet传递给
gevent.joinall
时,为什么会发生这种情况


如何确保只执行那些实际传递给
gevent.joinall
的greenlet?

调用
greenlet.spawn()
时,您的greenlet会立即被调度。换句话说,当您调用
spawn()
时,会立即创建并启动它们。这就是为什么第一个greenlet完成了运行——两个greenlet都是从您生成它们的那一刻开始执行的,当您开始查找greenlet 1的结果时,它们都完成了执行

gevent.joinall()
不执行greenlet-它只告诉主线程(实际生成它们的线程)等待作为参数传入的线程完成运行。不调用
joinall
会导致主线程在到达
joinall()
中的greenlet结果之前完成并退出,那么谁来处理它们的结果呢

在这里,为了看到
gevents
的行为符合您的要求,您做了两件应该更改的事情:

  • 您在控制台REPL中调用了
    joinall()
    ,而不是从脚本调用的

    在这里,主线程REPL保证不会在 greenlet返回,因为REPL仅在调用
    exit()时结束
    或表示EOF。然而,在一个没有即时用户交互的脚本中,你没有那种奢侈的享受——当脚本中没有什么事情可做时,执行就结束了。这就是为什么我们调用
    join()

    在控制台中调用
    joinall()
    没有任何意义(尽管如果您想要保证下次在greenlet上调用函数时,您将从greenlet获得结果,这是一个好主意)

  • 如果要保证只执行greenlet 1而不执行greenlet 2,则不应该调用
    spawn()
    。而是:

    要启动新的greenlet,请将目标函数及其参数传递给 Greenlet构造函数和调用start():

    >g=Greenlet(myfunction,'arg1','arg2',kwarg1=1)

    >g.start()

    或者使用classmethod
    spawn()
    ,这是一个具有相同功能的快捷方式:

    g=Greenlet.spawn(myfunction,'arg1','arg2',kwarg1=1)


使用
start
指示greenlet此时应开始运行是一个好主意。因此:创建两个greenlet对象,并仅对其中一个对象调用
start
,以仅执行该对象

当您调用
greenlet.spawn()
时,您的greenlet将立即被调度。换句话说,当您调用
spawn()
时,会立即创建并启动它们。这就是为什么第一个greenlet完成了运行——两个greenlet都是从您生成它们的那一刻开始执行的,当您开始查找greenlet 1的结果时,它们都完成了执行

gevent.joinall()
不执行greenlet-它只告诉主线程(实际生成它们的线程)等待作为参数传入的线程完成运行。不调用
joinall
会导致主线程在到达
joinall()
中的greenlet结果之前完成并退出,那么谁来处理它们的结果呢

在这里,为了看到
gevents
的行为符合您的要求,您做了两件应该更改的事情:

  • 您在控制台REPL中调用了
    joinall()
    ,而不是从脚本调用的

    在这里,主线程REPL保证不会在 greenlet返回,因为REPL仅在调用
    exit()时结束
    或表示EOF。然而,在一个没有即时用户交互的脚本中,你没有那种奢侈的享受——当脚本中没有什么事情可做时,执行就结束了。这就是为什么我们调用
    join()

    在控制台中调用
    joinall()
    没有任何意义(尽管如果您想要保证下次在greenlet上调用函数时,您将从greenlet获得结果,这是一个好主意)

  • 如果要保证只执行greenlet 1而不执行greenlet 2,则不应该调用
    spawn()
    。而是:

    要启动新的greenlet,请将目标函数及其参数传递给 Greenlet构造函数和调用start():

    >g=Greenlet(myfunction,'arg1','arg2',kwarg1=1)

    >g.start()

    或者使用classmethod
    spawn()
    ,这是一个具有相同功能的快捷方式:

    g=Greenlet.spawn(myfunction,'arg1','arg2',kwarg1=1)

使用
start
指示greenlet此时应开始运行是一个好主意。因此:创建两个greenlet对象,并仅对其中一个对象调用
start
,以仅执行该对象

gevent.joinall()
只等待作为参数传入的greenlet完成并将其与主线程连接。据我所知,它不会阻止任何其他线程的执行—只是告诉主线程在Greenlet完成运行之前不要退出。
gevent.joinall()
只等待作为参数传入的Greenlet完成并将其与主线程连接。据我所知,这是真的