1

当主脚本被杀死时,我试图停止 python 中的线程。但是由于线程每小时启动一次,我如何立即停止线程?

def interval():
    ###the actual work being done here###
    try:
        threading.Timer(3600, interval).start()
    except (KeyboardInterrupt, SystemExit):
        print "Exiting"
        cleanup_stop_interval();
        sys.exit()
interval()
4

3 回答 3

2

像这样杀死一个线程是个坏主意,因为它可能

  • 持有资源
  • 成为其他线程的父级

处理这个问题的正确方法是有一个 exit_request 标志,每个线程都会定期检查它是否是他退出的时间,并等待它通过使用退出join()

于 2012-12-25T12:24:07.890 回答
2

您可以考虑使用sched.scheduler而不是threading.Timer此处。有一些区别需要注意:

  • sched.scheduler在主进程中运行所有内容,而不是在线程中。
  • 如果当前进程花费的时间超过delay几秒,则计划的事件将在当前调用完成interval开始 。threading.Timer工作方式不同——如果完成的工作 interval超过一个小时,就会有多个线程 interval同时运行。

我猜你真的不希望多个interval同时运行,所以sched.scheduler在这里可能比threading.Timer.


import timeit
import sched
import time
import logging
import sys

logger = logging.getLogger(__name__)
logging.basicConfig(level = logging.DEBUG,
                    format = '%(threadName)s: %(asctime)s: %(message)s',
                    datefmt = '%H:%M:%S')
schedule = sched.scheduler(timeit.default_timer, time.sleep)
delay = 5 # change to 3600 to schedule event in 1 hour

def interval():
    logger.info('All work and no play makes Jack a dull boy.')
    schedule.enter(delay = delay, priority = 1, action = interval, argument = ())
    # Uncomment this to see how scheduled events are delayed if interval takes a
    # long time. 
    # time.sleep(10) 

schedule.enter(delay = 0, priority = 1, action = interval, argument = ())
try:
    schedule.run()
except (KeyboardInterrupt, SystemExit):
    print('Exiting')
    sys.exit()
于 2012-12-25T13:36:08.863 回答
0

你不能从另一个线程中停止一个线程。您可能想要的是使线程成为守护线程,这意味着即使线程仍然处于活动状态,进程也会退出:

http://docs.python.org/2/library/threading.html#threading.Thread.daemon

守护进程

一个布尔值,指示此线程是否为守护线程 (True) 或不是 (False)。这必须在调用 start() 之前设置,否则会引发 RuntimeError。它的初始值继承自创建线程;主线程不是守护线程,因此在主线程中创建的所有线程默认为 daemon = False。

当没有活着的非守护线程时,整个 Python 程序退出。

请注意,如果进程在该线程执行其工作的中间结束,您仍然可能会遇到问题。如果你想防止这种情况发生,那么让线程经常唤醒以检查它是否应该干净地退出。

于 2012-12-25T12:18:20.603 回答