在Python中杀死线程的各种方法

2025 年 1 月 5 日 | 阅读 10 分钟

引言

在本教程中,我们将学习 Python 中终止线程的各种方法。总的来说,过快地终止线程被认为是不好的编程实践。过早终止可能会导致重要的资源未被正确关闭。但是,偶尔您可能需要终止线程,或者可能会发生中断。Python 中有许多终止线程的方法。方法如下:

  1. 在 Python 线程中引发异常
  2. 设置或重置停止标志
  3. 使用跟踪来终止线程
  4. 使用 multiprocessing 模块终止线程
  5. 通过将线程设置为守护线程来终止 Python 中的线程
  6. 使用隐藏函数 _stop() 终止线程

现在,我们在以下部分讨论这些方法:

1. 在 Python 线程中引发异常

在线程中引发异常是终止 Python 线程的一种方法。此方法使用 PyThreadState_SetAsyncExc() 在线程中引发异常。下面我们提供了一个示例:

输出

现在,我们在机器上运行上述代码,然后我们将看到,当调用 exception_raise () 函数时,目标函数的 run() 函数将终止。这是因为当发生异常时,控制流会跳出 try 块并终止 run() 函数。可以使用 join() 函数来终止线程。如果没有 exception_run () 函数,目标函数 run() 将永远运行,并且不会调用 join() 函数来终止线程。输出现在如下所示:

running Thread
running Thread
running Thread
running Thread
running Thread
running Thread
running Thread
running Thread
running Thread

2. 设置或重置停止标志

设置或重置停止标志是终止 Python 线程的一种方法。我们可以定义一个停止标志来终止线程,线程会不时地检查该标志。下面我们提供了一个示例:

输出

现在,我们编译并运行上述代码。然后我们找到输出,如下所示:

Thread is running
Thread is killed

在上面的代码中,当设置全局变量 thread_stop 时,目标函数 thread_run() 将结束,并且将使用 t.join() 来执行线程 t。但是出于某些原因,人们会避免使用全局变量。在这些情况下,可以传递函数对象项来提供类似的功能。代码如下:

输出

上述代码中传递的函数对象始终返回本地 thread_stop 变量的值。在 thread_run() 函数中检查此值;一旦重置 thread_stop,thread_run() 函数将终止,并且线程可能会被终止。现在,我们编译并运行上述代码。然后我们找到输出,如下所示:

Thread is running
Thread is killed

3. 使用跟踪来终止线程

使用跟踪是终止 Python 线程的一种方法。此方法通过改进对每个线程的跟踪来工作。每一行都会自行终止,并在检测到特定条件或标志时立即断开线程连接。下面我们提供了一个示例:

输出

在此代码中,start() 已被轻微修改,以使用 settrace() 来设置要运行的跟踪。本地跟踪的目的是,当消息的中断(杀死)标志被设置时,当下一行代码执行时将引发 SystemExit 异常,从而结束对目标函数 fun 的获取。当前线程可以使用 join() 终止。现在,我们编译并运行上述代码。然后我们找到输出,如下所示:

Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is killed

4. 使用 multiprocessing 模块终止线程

使用 multiprocessing 模块是终止 Python 线程的一种方法。Python 的 multiprocessing 模块允许您创建进程,类似于使用 threading 模块创建线程。multithreading 模块的接口与 threading 模块类似。例如,在给定的代码中,我们创建了三个编号从 1 到 9 的线程(进程)。下面我们提供了一个示例:

输出

现在,我们编译并运行上述代码。然后我们找到输出,如下所示:

Thread is:0& prints is:0
Thread is:1& prints is:1
Thread is:0& prints is:0Thread is:1& prints is:2

Thread is:1& prints is:3Thread is:0& prints is:0

Thread is:0& prints is:0Thread is:1& prints is:4

Thread is:0& prints is:0Thread is:1& prints is:5

Thread is:0& prints is:0Thread is:1& prints is:6

Thread is:0& prints is:0Thread is:1& prints is:7

Thread is:0& prints is:0Thread is:1& prints is:8

Thread is:1& prints is:9Thread is:0& prints is:0

Thread is:0& prints is:0Thread is:1& prints is:10

Thread is:0& prints is:0Thread is:1& prints is:11

Thread is:0& prints is:0Thread is:1& prints is:12

上述代码也可以使用 multiprocessing 方法来工作,只需很少的更改。下面我们提供了一个示例:

输出

尽管两个模块的接口相似,但两个模块的用法完全不同。每个全局线程实现都不同,并且进程是相互独立的。因此,终止线程的方法比终止进程的方法更安全。Process 类提供了一个方法,即 terminate() 方法。此方法用于终止或杀死进程。现在,我们编译并运行上述代码。然后我们找到输出,如下所示:

Thread is:0& prints is:0
Thread is:1& prints is:1
Thread is:0& prints is:0Thread is:1& prints is:2

Thread is:1& prints is:3Thread is:0& prints is:0

Thread is:0& prints is:0Thread is:1& prints is:4

Thread is:0& prints is:0Thread is:1& prints is:5

Thread is:0& prints is:0Thread is:1& prints is:6

Thread is:0& prints is:0Thread is:1& prints is:7

Thread is:0& prints is:0Thread is:1& prints is:8

Thread is:1& prints is:9Thread is:0& prints is:0

Thread is:0& prints is:0Thread is:1& prints is:10

Thread is:0& prints is:0Thread is:1& prints is:11

Thread is:0& prints is:0Thread is:1& prints is:12

现在,让我们回到最初的问题。例如,在上面的代码中,我们希望在过去 0.03 秒后终止所有进程。multiprocessing 模块在下面的代码中使用了此函数:

输出

尽管两种模式有不同的用途。上述代码中的 multiprocessing 模块提供了类似于终止线程的功能。因此,当我们需要在 Python 中使用线程切割时,我们可以使用 multiprocessing 作为一种简单的替代方案。现在,我们编译并运行上述代码。然后我们找到输出,如下所示:

Processing is: 0 & prints is: 0
Processing is: 1 & prints is: 1
Processing is: 2 & prints is: 2
Processing is: 3 & prints is: 3
Processing is: 0 & prints is: 0
Processing is: 1 & prints is: 2
Processing is: 2 & prints is: 4
> Processing is: 0 & prints is: 0
Processing is: 1 & prints is: 3
Processing is: 2 & prints is: 6
Processing is: 0 & prints is: 0
Processing is: 1 & prints is: 4
Processing is: 2 & prints is: 8
Processing is: 0 & prints is: 0
Processing is: 1 & prints is: 5
Processing is: 2 & prints is: 10

5. 通过将线程设置为守护线程来终止 Python 中的线程

终止 Python 线程的另一种方法是将其设置为守护线程。守护线程是在主任务退出时被终止的线程。下面我们提供了一个示例:

输出

请注意,线程 t1 仍然处于活动状态,阻止主任务退出 sys.exit()。在 Python 中,非守护线程会阻止主程序退出。但是,当主程序退出时,守护线程本身将被终止。现在,我们编译并运行上述代码。然后我们找到输出,如下所示:

The thread is alive
The thread is alive
The thread is alive
The thread is alive
The thread is alive
The thread is alive
The thread is alive

换句话说,所有守护线程将在主程序退出时被终止。要将线程发布为守护线程,我们将 daemon 参数关键字设置为 True。对于给定代码中的示例,它显示了守护线程的属性。示例如下:

输出

现在,我们编译并运行上述代码。请注意,当主服务关闭时,线程 t1 将被终止。事实证明,此方法在可用于终止程序线程的情况下非常有用。请注意,在 Python 中,主程序在所有非守护线程被终止时退出,无论幸存线程的数量如何。因此,守护线程所持有的资源,如文件句柄、数据库操作等,将不会得到正确处理。Python 程序中的主线程不是守护线程。强制终止线程仅在您确定这样做不会导致泄漏或死锁时才推荐。我们找到输出,如下所示:

The thread is alive
The thread is alive
The thread is alive
The thread is alive
The thread is alive
The thread is alive
An exception has occurred, use %tb to see the full traceback.

SystemExit

The thread is alive
The thread is alive
The thread is alive

6. 使用隐藏函数 _stop() 终止线程

使用隐藏函数 _stop() 是终止 Python 线程的一种方法。我们使用隐藏函数 _stop() 来终止线程。此函数未被记录,但将在下一版本 Python 中消失。下面我们提供了一个示例:

输出

现在,我们编译并运行上述代码。然后我们找到输出,如下所示:

Hello Coders
Hello Coders
Hello Coders
Hello Coders
Hello Coders
Hello Coders
Hello Coders
Hello Coders

结论

在本教程中,我们将学习 Python 中终止线程的各种方法。基本上,过快地终止线程被认为是不好的编程实践。在这里,我们学习了 Python 中终止线程的六种方法,并提供了相应方法的示例。