大多数Pythonic方式在一段时间后杀死一个线程

时间:2016-01-02 04:01:41

标签: python multithreading

我想在一个线程中运行一个进程(它在一个大型数据库表上进行迭代)。线程正在运行时,我只想让程序等待。如果该线程花费的时间超过30秒,我想杀死该线程并执行其他操作。通过杀死线程,我的意思是我希望它能够停止活动并优雅地释放资源。

我认为最好的方法是通过Thread() join(delay)is_alive()函数以及Event。使用join(delay)我可以让程序等待30秒以完成线程,并且通过使用is_alive()函数,我可以确定线程是否已完成其工作。如果它还没有完成它的工作,那么事件就会被设置,并且线程知道在那时停止工作。

这种方法是否有效,这是解决我的问题陈述的最蟒蛇方式吗?

以下是一些示例代码:

import threading
import time

# The worker loops for about 1 minute adding numbers to a set
# unless the event is set, at which point it breaks the loop and terminates
def worker(e):
    data = set()
    for i in range(60):
        data.add(i)
        if not e.isSet():
            print "foo"
            time.sleep(1)
        else:
            print "bar"
            break

e = threading.Event()
t = threading.Thread(target=worker, args=(e,))
t.start()

# wait 30 seconds for the thread to finish its work
t.join(30)
if t.is_alive():
    print "thread is not done, setting event to kill thread."
    e.set()
else:
    print "thread has already finished."

3 个答案:

答案 0 :(得分:5)

在这种情况下使用事件可以很好地作为信号机制,并且 实际上建议threading module docs

  

如果您希望线程正常停止,请使它们成为非守护进程并使用   适当的信令机制,如Event

在验证线程终止时,超时几乎总是会为其提供空间 错误。因此,在使用带有超时的.join()初始化时 决定触发事件是好的,最终验证应该使用a .join()没有超时。

# wait 30 seconds for the thread to finish its work
t.join(30)
if t.is_alive():
    print "thread is not done, setting event to kill thread."
    e.set()
    # The thread can still be running at this point. For example, if the 
    # thread's call to isSet() returns right before this call to set(), then
    # the thread will still perform the full 1 second sleep and the rest of 
    # the loop before finally stopping.
else:
    print "thread has already finished."

# Thread can still be alive at this point. Do another join without a timeout 
# to verify thread shutdown.
t.join()

这可以简化为:

# Wait for at most 30 seconds for the thread to complete.
t.join(30)

# Always signal the event. Whether the thread has already finished or not, 
# the result will be the same.
e.set()

# Now join without a timeout knowing that the thread is either already 
# finished or will finish "soon."
t.join()

答案 1 :(得分:1)

我已经迟到了这个游戏,但我一直在与a similar question进行摔跤,以下似乎都能完美地解决这个问题并让我做一些基本的线程状态检查和守护进程子线程退出时清理:

import threading
import time
import atexit

def do_work():

  i = 0
  @atexit.register
  def goodbye():
    print ("'CLEANLY' kill sub-thread with value: %s [THREAD: %s]" %
           (i, threading.currentThread().ident))

  while True:
    print i
    i += 1
    time.sleep(1)

t = threading.Thread(target=do_work)
t.daemon = True
t.start()

def after_timeout():
  print "KILL MAIN THREAD: %s" % threading.currentThread().ident
  raise SystemExit

threading.Timer(2, after_timeout).start()

收率:

0
1
KILL MAIN THREAD: 140013208254208
'CLEANLY' kill sub-thread with value: 2 [THREAD: 140013674317568]

答案 2 :(得分:0)

我还在努力关闭正在等待接收通知的线程。 尝试过由user5737269在此处提供解决方案,但对我而言确实不起作用。它被卡在第二个join语句中(没有超时)。挣扎了很多,但是没有找到解决这个问题的任何方法。经过一段时间思考后得到了以下解决方案: 我的线程正在等待接收que中的消息。如果20秒钟内未收到任何通知,我想关闭此线程。因此,在20秒后,我正在向此队列写入一条消息,以便线程自行终止。 这是代码:

 q = Queue.Queue()
 t.join(20)
    if t.is_alive():
        print("STOPPING THIS THREAD ....")
        q.put("NO NOTIFICATION RECEIVED")
        t.join(20)
    else:
        print("Thread completed successfully!!")

这对我有用。希望这个想法对某人有帮助!