主程序结束时如何终止线程?


Answers:


46

检查这个问题。正确的答案对如何以正确的方式终止线程有很好的解释: 有没有办法杀死Python中的线程?

要使线程在键盘中断信号(ctrl + c)上停止,您可以在退出之前捕获异常“ KeyboardInterrupt”并进行清除。像这样:

try:
    start_thread()  
except (KeyboardInterrupt, SystemExit):
    cleanup_stop_thread()
    sys.exit()

这样,您可以控制程序突然终止时的处理方式。

您还可以使用内置的信号模块,该模块可用于设置信号处理程序(在特定情况下为SIGINT信号):http : //docs.python.org/library/signal.html


非常感谢您的回复。我可能没有正确说明问题。在该问题给出的示例中,仍然有必要执行线程的stop()函数。当我通过ctrl + C异常终止程序时,不会发生这种情况。因此,我的问题有点像,“如果主线程流被中断,如何调用mythread.stop()函数”
facha 2010年

1
cleanup_stop_thread()一个全球性的功能,我可以使用?还是我需要实施它?
alper

@alper,我认为也许这只是示例,可以实现某些功能。您应该实施
Leonardo Rick

98

如果使工作线程守护程序线程成为线程,则当所有非守护程序线程(例如主线程)退出时它们将死亡。

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


4
感谢简单准确的答案,默认的threading.Thread守护进程状态isDaemon()为False,请通过设置为True setDaemon(True)

3
这可以回答问题,并且可以正常工作。操作员通常不询问如何干净地退出线程。
Johannes Overmann

1
isDaemon()setDaemon()老getter / setter方法(根据连接的文档以上),只是使用daemon=Truethreading.Thread()
fabio.sang

1
注意,使用守护线程可能会导致其他问题,可能不是你想要的位置:stackoverflow.com/questions/20596918/...
Doopy

为了避免使用守护线程和干净杀线程,请参见stackoverflow.com/questions/58910372/...
帕特-笑

14

尝试将子线程启用为守护程序线程。

例如:

推荐的:

from threading import Thread

t = Thread(target=<your-method>)
t.daemon = True  # This thread dies when main thread (only non-daemon thread) exits.
t.start()

排队:

t = Thread(target=<your-method>, daemon=True).start()

旧API:

t.setDaemon(True)
t.start()

当您的主线程终止时(例如,当我按Ctrl+时C),其他线程也将被上述说明杀死。


1
注意,使用守护线程可能会导致其他问题,也有可能不是你想要的这里:stackoverflow.com/questions/20596918/...
Doopy

12

使用Python标准库的atexit模块来注册在主线程的任何合理的“干净”终止(包括未捕获的异常)上调用(在主线程上)的“终止”函数KeyboardInterrupt。这样的终止函数可以(尽管不可避免地在主线程中!)调用stop您需要的任何函数;加上将线程设置为的可能性daemon,可以为您提供正确设计所需系统功能的工具。


请注意,此方法无需在2.6.5之前的Python版本中使用守护线程即可工作,请参见stackoverflow.com/questions/3713360/…的答案。不幸的是,恕我直言,因为关闭过程中的守护进程线程在python 3.4(bugs.python.org/issue19466)之前有点混乱。如果您停止在atexit处理程序中加入守护程序线程,那么一切都应该没问题,但要以串行化线程拆除的代价(可能微不足道)。
NeilenMarais

请注意,由于atexit.register()Python模块中的延迟调用会导致发生奇怪的事情,从而导致终止过程在的执行之后执行multiprocessing。我在处理Queuedaemon线程方面遇到了这个问题:使用多重处理Queue和Thread在程序退出时出现“ EOF错误”
Delgan

显然,在现代版本的Python(例如3.7.4+)中,atexit当非守护程序线程处于活动状态并且主线程退出时,不会调用处理程序。请参阅使用atexit终止线程时脚本卡在出口上
martineau

9

如果您像这样生成一个线程myThread = Thread(target = function),然后执行myThread.start(); myThread.join()。启动CTRL-C时,主线程不会退出,因为它正在等待该阻塞myThread.join()调用。要解决此问题,只需在.join()调用中添加超时即可。超时时间可以是您希望的时间。如果希望它无限期地等待,只需设置一个非常长的超时(如99999)即可。这样做也是一种好习惯,myThread.daemon = True当主线程(非守护程序)退出时,所有线程都退出。


myThread.daemon = True是解决这个问题的绝妙方法。
布兰农

5
@Brannon.daemon=True并不是一个解决方案。检查该线程以获取解释:stackoverflow.com/a/20598791/5562492
Odyssee'Octssee

2

守护进程线程被恶意破坏,因此不会执行任何终结器指令。一个可能的解决方案是检查主线程是否仍然存在而不是无限循环。

例如Python 3:

while threading.main_thread().isAlive():
    do.you.subthread.thing()
gracefully.close.the.thread()

请参阅检查主线程是否仍在另一个线程中

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.