我遇到了问题,情况就像下面的代码一样。目标函数(等待)是在一个while循环或花了很长时间,所以我想杀死微线程。如何杀死thread1?
注意:用户的微线程可能是CPU绑定操作(例如没有任何IO操作的while循环。)
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')
gevent.killall()
和thread.kill()
都要求thread scheduler
运行,它们不会像我们预期的那样终止线程。
答案 0 :(得分:0)
你在那里做了很多不必要的工作。您可以简单地将秒作为关键字参数传递给join()
,如下所示:
>>> 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秒后终止正在运行wait()
的greenlet。你无法抓住Timeout
,因为join()
会抓住它,只要超时就是那个,就会默默地杀死greenlet除外。以下是来自join()
greenlet.py
摘录
try:
t = Timeout.start_new(timeout)
... SNIP ...
except Timeout as ex:
self.unlink(switch)
if ex is not t:
raise
您也可以使用kill()
杀死greenlet。我认为这是错误的方法,但无论如何我都会添加这个例子。以下将运行greenlet 5秒然后杀死它:
>>> g = gevent.spawn(wait)
>>> with gevent.Timeout(5, False):
... g.join()
... g.kill()
...
答案 1 :(得分:0)
只有“等待”微线程有机会切换时,您的代码才有效。如果你控制线程的代码,你可以通过调用gevent.sleep来实现。否则,如果您的线程代码是在python中实现并使用IO操作,您可以尝试通过以下方式修补python函数:
from gevent.monkey import patch_all
patch_all()
这将允许您的线程在遇到各种IO操作时切换。
答案 2 :(得分:-2)
我遇到同样的问题,我必须杀死一个greenlet线程(它有用户编写的代码)。
在CPU绑定操作的情况下,Gevent的开关和超时将无效!
我们不能假设用户编写了没有死循环且具有CPU绑定操作的正确代码。
最后,我使用“Signal”API来解决这个问题。
请参阅https://docs.python.org/2/library/signal.html
关于Gevent的切换和超时:https://groups.google.com/forum/#!topic/gevent/eBj9YQYGBbc
以下代码可能适合您。
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))