Python 当gevent微线程处于while循环中时,如何停止它?
我有一个问题,情况就像下面的代码。目标函数(wait)处于while循环中或花费了大量时间,因此我想杀死微线程。如何杀死线1 注意:用户的微线程可能是CPU限制的操作(例如,没有任何IO操作的while循环)Python 当gevent微线程处于while循环中时,如何停止它?,python,while-loop,timeout,gevent,Python,While Loop,Timeout,Gevent,我有一个问题,情况就像下面的代码。目标函数(wait)处于while循环中或花费了大量时间,因此我想杀死微线程。如何杀死线1 注意:用户的微线程可能是CPU限制的操作(例如,没有任何IO操作的while循环) gevent.killall()和thread.kill()都需要运行线程调度程序,它们不会像我们预期的那样终止线程。您在那里做了很多不必要的工作。您只需将秒数作为关键字参数传递给以下对象: >>> import gevent >>> def wait(
gevent.killall()
和thread.kill()
都需要运行线程调度程序,它们不会像我们预期的那样终止线程。您在那里做了很多不必要的工作。您只需将秒数作为关键字参数传递给以下对象:
>>> import gevent
>>> def wait():
... while True:
... print("In loop")
... gevent.sleep(1) # To not fill the screen..
...
>>>
>>> g = gevent.spawn(wait)
>>> g.join(timeout=5)
以下内容将在5秒后杀死正在运行的greenletwait()
。您无法捕获超时
,因为它将为您捕获超时,并且只要超时是它例外的超时,就可以无声地杀死greenlet。以下是的源代码中的一个片段
你也可以用它杀死一只小绿猫。我认为这是一个错误的方法,但我还是要添加一个例子。以下操作将运行greenlet 5秒,然后将其杀死:
>>> g = gevent.spawn(wait)
>>> with gevent.Timeout(5, False):
... g.join()
... g.kill()
...
只有当“等待”微线程有机会切换时,代码才会工作。如果控制线程的代码,可以通过调用gevent.sleep来实现。否则,如果线程的代码是用python实现的,并且使用IO操作,则可以尝试通过以下方式对python函数进行修补:
from gevent.monkey import patch_all
patch_all()
这将允许您的线程在点击各种IO操作时切换。我遇到同样的问题,我必须杀死一个greenlet线程(它有用户编写的代码)
在CPU受限的情况下,Gevent的开关和超时将不起作用强>
我们不能假设用户写的代码是正确的,因为没有死环,死环的操作是CPU限制的
import gevent
from gevent import Timeout
def wait():
while(1):
pass
print 'end'
timer = Timeout(1).start()
thread1 = gevent.spawn(wait)
try:
thread1.join(timeout=timer)
except Timeout:
print('Thread 1 timed out')
最后,我使用“信号”API来解决这个问题
请参阅
关于Gevent的开关和超时:
以下代码可能供您参考
from gevent.monkey import patch_all;patch_all()
import gevent
import time
def fucking_loop():
while True:
pass
def fucking_loop_with_timeout():
with gevent.Timeout(10):
while True:
pass
def fail_to_kill():
deadline = time.time() + 10
thread = gevent.spawn(fucking_loop)
while deadline > time.time():
# gevent.sleep will switch out of main thread
gevent.sleep(1)
# This line of code will never been executed
# because gevent will not switch to main thread.
thread.kill()
def fail_to_kill_2():
thread = gevent.spawn(fucking_loop)
# Will never timeout because of the same reason
fucking_loop_with_timeout()
# This line of code will never been executed
# because gevent will not switch to main thread.
thread.join(timeout=10)
thread.kill()
def kill_fucking_loop_works():
import signal
timeout = 10
thread = gevent.spawn(fucking_loop)
def kill_thread(*args, **kwargs):
if not thread.dead:
thread.kill(timeout=1)
signal.signal(signal.SIGALRM, kill_thread)
signal.alarm(int(timeout))
您可以使用gevent.killall()!gevent.killall()将无法按预期工作,我在问题中添加了一些说明。谢谢你的评论。对不起,我没说清楚。我的意思是像一个while循环,但是你没有机会添加gevent.sleep(1)来让这个greenlet睡眠。就像调用第三方库函数一样,它很长一段时间没有响应。@user3611389我认为,如果net无法进行上下文切换,您不可能通过超时greenlet来解决长阻塞问题。谢谢您的回答,正如您所说,我们没有更改gevent的超时或终止微线程,因为我们没有机会执行上下文切换,我们必须运行非协作线程或使用系统计时器API。这个答案有助于解释问题中的代码不起作用的原因,谢谢。谢谢你的回答,但是在CPU受限的情况下,交换机没有机会运行。这个答案解决不了问题,无论如何,谢谢。过一会儿我会更详细地描述我的问题。
from gevent.monkey import patch_all;patch_all()
import gevent
import time
def fucking_loop():
while True:
pass
def fucking_loop_with_timeout():
with gevent.Timeout(10):
while True:
pass
def fail_to_kill():
deadline = time.time() + 10
thread = gevent.spawn(fucking_loop)
while deadline > time.time():
# gevent.sleep will switch out of main thread
gevent.sleep(1)
# This line of code will never been executed
# because gevent will not switch to main thread.
thread.kill()
def fail_to_kill_2():
thread = gevent.spawn(fucking_loop)
# Will never timeout because of the same reason
fucking_loop_with_timeout()
# This line of code will never been executed
# because gevent will not switch to main thread.
thread.join(timeout=10)
thread.kill()
def kill_fucking_loop_works():
import signal
timeout = 10
thread = gevent.spawn(fucking_loop)
def kill_thread(*args, **kwargs):
if not thread.dead:
thread.kill(timeout=1)
signal.signal(signal.SIGALRM, kill_thread)
signal.alarm(int(timeout))