有什么方法可以杀死线程吗?
是否可以在不设置/检查任何标志/信号量/等的情况下终止运行线程?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
是否可以在不设置/检查任何标志/信号量/等的情况下终止运行线程?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(30)
通常,用python和任何语言杀死线程是一个不好的模式。考虑以下情况:
如果您负担得起的话,处理此问题的好方法(如果您要管理自己的线程),则是具有一个exit_request标志,每个线程都会在常规间隔上检查,以查看是否是时候退出它了。
例如:
在此代码中,您应该在线程退出时在线程上调用
stop()
,并等待线程使用JOIN正确退出()
。线程应定期检查停止标志。但是,在某些情况下,您确实需要杀死线程。一个例子是,当您包裹一个忙于长时间通话的外部库时,您想中断它。
以下代码允许(有些限制)在python线程中提高例外:(
基于 tomer filiba。 的旧版本。
dev/python/pystate.c“ rel =“ noreferrer”> python 抓住中断。
此代码的良好用法模式是让线程捕获特定的例外并执行清理。这样,您可以中断一项任务并仍然进行适当的清理。
It is generally a bad pattern to kill a thread abruptly, in Python, and in any language. Think of the following cases:
The nice way of handling this, if you can afford it (if you are managing your own threads), is to have an exit_request flag that each thread checks on a regular interval to see if it is time for it to exit.
For example:
In this code, you should call
stop()
on the thread when you want it to exit, and wait for the thread to exit properly usingjoin()
. The thread should check the stop flag at regular intervals.There are cases, however, when you really need to kill a thread. An example is when you are wrapping an external library that is busy for long calls, and you want to interrupt it.
The following code allows (with some restrictions) to raise an Exception in a Python thread:
(Based on Killable Threads by Tomer Filiba. The quote about the return value of
PyThreadState_SetAsyncExc
appears to be from an old version of Python.)As noted in the documentation, this is not a magic bullet because if the thread is busy outside the Python interpreter, it will not catch the interruption.
A good usage pattern of this code is to have the thread catch a specific exception and perform the cleanup. That way, you can interrupt a task and still have proper cleanup.
a
p. terminate(
)我想杀死线程,但不想使用标志/锁/信号/信号量/事件/其他,我将线程宣传到完整的过程。对于仅使用几个线程的代码,开销还不错。
例如,这很方便以轻松终止执行阻止I/O转换的“线程”
是微不足道的:在相关代码中替换所有
threading.thread.thread
用supperprocessing.processing.process.process.process
and code>和所有queue.queue.queue
with多处理。Queue
,并将p.terminate()
的所需调用添加到您的父程进程中p
请参阅 python文档,用于
python a>。
例子:
A
multiprocessing.Process
canp.terminate()
In the cases where I want to kill a thread, but do not want to use flags/locks/signals/semaphores/events/whatever, I promote the threads to full blown processes. For code that makes use of just a few threads the overhead is not that bad.
E.g. this comes in handy to easily terminate helper "threads" which execute blocking I/O
The conversion is trivial: In related code replace all
threading.Thread
withmultiprocessing.Process
and allqueue.Queue
withmultiprocessing.Queue
and add the required calls ofp.terminate()
to your parent process which wants to kill its childp
See the Python documentation for
multiprocessing
.Example:
没有官方的API要这样做,不。
您需要使用平台API杀死线程,例如pthread_kill或terminateThread。您可以通过pythonwin或通过CTYPE访问此类API。
请注意,这本质上是不安全的。这可能会导致无法收集的垃圾(从堆栈框架的当地变量变成垃圾),并可能导致死锁,如果被杀死的线程在被杀死时具有GIL。
There is no official API to do that, no.
You need to use platform API to kill the thread, e.g. pthread_kill, or TerminateThread. You can access such API e.g. through pythonwin, or through ctypes.
Notice that this is inherently unsafe. It will likely lead to uncollectable garbage (from local variables of the stack frames that become garbage), and may lead to deadlocks, if the thread being killed has the GIL at the point when it is killed.
如果要终止整个程序,则可以将线程设置为“守护程序”。参见
thread.daemon.daemon
If you are trying to terminate the whole program you can set the thread as a "daemon". see
Thread.daemon
正如其他人提到的那样,规范是设置停止标志。对于轻巧的东西(没有线程的子分类,没有全局变量),可以选择lambda回调。 (请注意
中的括号,如果stop()
。)用
print()
替换为pr()
始终flushes(sys) .stdout.flush()
)可以提高外壳输出的精度。(仅在Windows/Eclipse/Python3.3上测试)
As others have mentioned, the norm is to set a stop flag. For something lightweight (no subclassing of Thread, no global variable), a lambda callback is an option. (Note the parentheses in
if stop()
.)Replacing
print()
with apr()
function that always flushes (sys.stdout.flush()
) may improve the precision of the shell output.(Only tested on Windows/Eclipse/Python3.3)
在Python中,您根本无法直接杀死线程。
如果您真的不需要一个线程(!),您可以做什么,而不是使用 螺纹 package ,是使用
多处理 package 。在这里,要杀死一个过程,您可以简单地调用该方法:
Python将杀死您的过程(通过Sigterm Signs在UNIX上,而在Windows上通过
terminateProcess()
呼叫)。使用队列或管道时请注意使用它! (它可能会损坏队列/管道中的数据)请注意,
多处理
和多处理。-eMaphore
以与螺纹的方式完全相同。事件
和螺纹。分别
。实际上,第一个是后者的克隆。如果您确实需要使用线程,则无法直接杀死它。但是,您可以做的是使用“守护程序线程” 。实际上,在Python中,可以将线程标记为 daemon :
当没有活着的非daemon线程时,主程序将退出。换句话说,当您的主线程(当然是非daemon线程)将完成其操作时,即使仍然有一些守护程序线程可行,该程序也会退出。
请注意,在调用
start()
方法之前,必须将线程设置为daemon
!当然,即使使用
多处理
,您也可以并且应该使用daemon
。在这里,当主要过程退出时,它试图终止其所有守护程序过程。最后,请注意,
sys.exit()
和os.kill()
不是选择。In Python, you simply cannot kill a Thread directly.
If you do NOT really need to have a Thread (!), what you can do, instead of using the threading package , is to use the
multiprocessing package . Here, to kill a process, you can simply call the method:
Python will kill your process (on Unix through the SIGTERM signal, while on Windows through the
TerminateProcess()
call). Pay attention to use it while using a Queue or a Pipe! (it may corrupt the data in the Queue/Pipe)Note that the
multiprocessing.Event
and themultiprocessing.Semaphore
work exactly in the same way of thethreading.Event
and thethreading.Semaphore
respectively. In fact, the first ones are clones of the latters.If you REALLY need to use a Thread, there is no way to kill it directly. What you can do, however, is to use a "daemon thread". In fact, in Python, a Thread can be flagged as daemon:
The main program will exit when no alive non-daemon threads are left. In other words, when your main thread (which is, of course, a non-daemon thread) will finish its operations, the program will exit even if there are still some daemon threads working.
Note that it is necessary to set a Thread as
daemon
before thestart()
method is called!Of course you can, and should, use
daemon
even withmultiprocessing
. Here, when the main process exits, it attempts to terminate all of its daemonic child processes.Finally, please, note that
sys.exit()
andos.kill()
are not choices.这基于 thread2-可杀死线程激活配方。
您需要调用
pythreadState_setaState_setAseNcexcc() /a>,仅通过
ctypes
模块。这仅在Python 2.7.3上进行了测试,但很可能与其他最近的2.x版本一起使用。
pythreadstate_setasyncexc()
仍然存在于Python 3中,以供向后兼容(但我尚未对其进行测试)。This is based on the thread2 -- killable threads ActiveState recipe.
You need to call
PyThreadState_SetAsyncExc()
, which is only available through thectypes
module.This has only been tested on Python 2.7.3, but it is likely to work with other recent 2.x releases.
PyThreadState_SetAsyncExc()
still exists in Python 3 for backwards compatibility (but I have not tested it).如果不与之合作,您绝对不应强行杀死线程。
可以删除任何保证尝试/最终阻止设置的保证
杀死线程 。
You should never forcibly kill a thread without cooperating with it.
Killing a thread removes any guarantees that try/finally blocks set up so you might leave locks locked, files open, etc.
The only time you can argue that forcibly killing threads is a good idea is to kill a program fast, but never single threads.
如果您要明确调用
time.sleep()
作为线程的一部分(例如,对某些外部服务进行轮询),则对Phillipe方法的改进是在event> Event
中使用超时'swait()
方法sleep> sleep()
例如:
然后运行
wait() > sleep()
并定期检查事件是您可以以较长的睡眠时间间隔进行编程,该线程几乎立即停止(否则您将是sleep()
in)和我认为,处理出口的代码非常简单。If you are explicitly calling
time.sleep()
as part of your thread (say polling some external service), an improvement upon Phillipe's method is to use the timeout in theevent
'swait()
method wherever yousleep()
For example:
Then to run it
The advantage of using
wait()
instead ofsleep()
ing and regularly checking the event is that you can program in longer intervals of sleep, the thread is stopped almost immediately (when you would otherwise besleep()
ing) and in my opinion, the code for handling exit is significantly simpler.您可以通过将跟踪安装到线程中,以杀死线程,以退出线程。有关一个可能的实现,请参见附件链接。
You can kill a thread by installing trace into the thread that will exit the thread. See attached link for one possible implementation.
Kill a thread in Python
绝对可以实现
thread.stop
方法,如以下示例代码:thread3
class似乎比thread2快于33%的代码运行代码2
类。附录:
有足够的了解Python的C API和使用
ctypes
模块,可以在需要时编写一种更有效的方法来停止线程。使用sys.settrace
的问题在于,跟踪功能在每次指令后运行。如果在需要中止的线程上提出异步异常,则不会产生执行速度惩罚。以下代码在这方面提供了一些灵活性:It is definitely possible to implement a
Thread.stop
method as shown in the following example code:The
Thread3
class appears to run code approximately 33% faster than theThread2
class.Addendum:
With sufficient knowledge of Python's C API and the use of the
ctypes
module, it is possible to write a far more efficient way of stopping a thread when desired. The problem with usingsys.settrace
is that the tracing function runs after each instruction. If an asynchronous exception is raised instead on the thread that needs to be aborted, no execution speed penalty is incurred. The following code provides some flexibility in this regard:如果您不杀死线程,那就更好了。
一种方法可能是将“尝试”块引入线程周期中,并在要停止线程时引发异常(例如,断路/返回/...阻止您的/while/while/...)。
我已经在我的应用程序上使用了此功能,它有效...
It is better if you don't kill a thread.
A way could be to introduce a "try" block into the thread's cycle and to throw an exception when you want to stop the thread (for example a break/return/... that stops your for/while/...).
I've used this on my app and it works...
我到这个游戏迟到了,但是我一直在用一个类似的问题,下面似乎都解决了对于我来说,这个问题非常完美,让我可以在守护程序的子线退出时进行一些基本的线程检查和清理:
产量:
I'm way late to this game, but I've been wrestling with a similar question and the following appears to both resolve the issue perfectly for me AND lets me do some basic thread state checking and cleanup when the daemonized sub-thread exits:
Yields:
可以使用以下方法来杀死线程:
即使是终止线程中的代码写在另一个模块中的螺纹的线程也可以使用。我们可以在该模块中声明一个全局变量,并使用它终止该模块中产生的线程。
我通常会使用它来终止程序退出的所有线程。这可能不是终止线程的理想方法,但可能会有所帮助。
Following workaround can be used to kill a thread:
This can be used even for terminating threads, whose code is written in another module, from main thread. We can declare a global variable in that module and use it to terminate thread/s spawned in that module.
I usually use this to terminate all the threads at the program exit. This might not be the perfect way to terminate thread/s but could help.
这是另一种方法,但是使用极其干净和简单的代码,它在2021年在Python 3.7中起作用:
从这里进行了改编: https://www.geeksforgeeks.org/python-different-ways-ways-to-kill-a-a-thread/
Here's yet another way to do it, but with extremely clean and simple code, that works in Python 3.7 in 2021:
Adapted from here: https://www.geeksforgeeks.org/python-different-ways-to-kill-a-thread/
t 是您的
线程
对象。阅读Python源(
模块/threadmodule.c
和python/thread_pthread.h
)您可以看到thread.thread.ender
是> pthread_t
类型,因此您可以执行任何操作pthread
可以在Python中使用libpthread
。t is your
Thread
object.Read the python source (
Modules/threadmodule.c
andPython/thread_pthread.h
) you can see theThread.ident
is anpthread_t
type, so you can do anythingpthread
can do in python uselibpthread
.我要补充的一件事是,如果您阅读,建议避免使用“恶魔”线程,当您不希望线程突然结束时,使用Paolo Rovelli a>。
从官方文件中:
我认为创建守护线的线程取决于您的应用程序,但总的来说(在我看来)最好避免杀死它们或使其守护。在多处理中,您可以使用
is_alive()
检查进程状态并“终止”以完成它们(也避免GIL问题)。但是,当您在Windows中执行代码时,您会发现更多问题。始终记住,如果您拥有“实时线程”,则Python解释器将持续到等待它们。 (因为这个守护者,如果不突然结束的话,可以为您提供帮助)。
One thing I want to add is that if you read official documentation in threading lib Python, it's recommended to avoid use of "demonic" threads, when you don't want threads end abruptly, with the flag that Paolo Rovelli mentioned.
From official documentation:
I think that creating daemonic threads depends of your application, but in general (and in my opinion) it's better to avoid killing them or making them daemonic. In multiprocessing you can use
is_alive()
to check process status and "terminate" for finish them (Also you avoid GIL problems). But you can find more problems, sometimes, when you execute your code in Windows.And always remember that if you have "live threads", the Python interpreter will be running for wait them. (Because of this daemonic can help you if don't matter abruptly ends).
有一个为此目的构建的库, stopit 。尽管此处列出的一些警告仍然适用,但至少该库提供了一种实现既定目标的常规,可重复的技术。
There is a library built for this purpose, stopit. Although some of the same cautions listed herein still apply, at least this library presents a regular, repeatable technique for achieving the stated goal.
只是为了建立 @SCB的想法(这正是我所需的)来创建一个具有自定义功能的KillableThread子类:
自然,就像@SBC一样,该线程不会等待运行新的循环以停止。在此示例中,您会看到“即将杀死线程”后立即打印的“杀死线程”消息,而不是再等4秒钟才能完成该线程(因为我们已经睡了6秒钟)。
KillableThread构造函数中的第二个参数是您的自定义函数(在此处print_msg)。 ARGS参数是在此处调用函数((“ Hello World”))时将使用的参数。
Just to build up on @SCB's idea (which was exactly what I needed) to create a KillableThread subclass with a customized function:
Naturally, like with @SBC, the thread doesn't wait to run a new loop to stop. In this example, you would see the "Killing Thread" message printed right after the "About to kill thread" instead of waiting for 4 more seconds for the thread to complete (since we have slept for 6 seconds already).
Second argument in KillableThread constructor is your custom function (print_msg here). Args argument are the arguments that will be used when calling the function (("hello world")) here.
An alternative is to use
signal.pthread_kill
< /a>发送停止信号。结果
An alternative is to use
signal.pthread_kill
to send a stop signal.result
虽然很旧,但这对于某些方案可能是一种方便的解决方案:
因此,它允许“线程在另一个线程的上下文中提高异常”,通过这种方式,终止线程可以处理终止,而无需定期检查中止标志。
但是,根据其原始源,此代码存在一些问题。
While it's rather old, this might be a handy solution for some:
So, it allows a "thread to raise exceptions in the context of another thread" and in this way, the terminated thread can handle the termination without regularly checking an abort flag.
However, according to its original source, there are some issues with this code.
令人震惊的是,您想要具有相同函数的多个线程,这是恕我直言,最简单的实现来阻止一个iD:
好的事情在这里,您可以具有相同的多个功能,并通过
停止它们。 functionName.stop
如果只想拥有一个函数的一个线程,则不需要记住ID。如果
doit.stop
&gt; 0。Asuming, that you want to have multiple threads of the same function, this is IMHO the easiest implementation to stop one by id:
The nice thing is here, you can have multiple of same and different functions, and stop them all by
functionname.stop
If you want to have only one thread of the function then you don't need to remember the id. Just stop, if
doit.stop
> 0.如 @kozyarchuk的答案跟踪起作用。由于此答案不包含代码,因此这是一个工作现成的示例:
它在打印
1
和2
后停止。3
未打印。As mentioned in @Kozyarchuk's answer, installing trace works. Since this answer contained no code, here is a working ready-to-use example:
It stops after having printed
1
and2
.3
is not printed.Python版本:3.8
使用守护程序线程执行我们想要的内容,如果我们要终止守护程序线程,我们需要的只是使父螺纹退出,那么系统将终止守护程序线程,而守护程序则创建了parent thread。
还支持Coroutine和Coroutine功能。
以下是ExitThread源代码
Python version: 3.8
Using daemon thread to execute what we wanted, if we want to daemon thread be terminated, all we need is making parent thread exit, then system will terminate daemon thread which parent thread created.
Also support coroutine and coroutine function.
below is ExitThread source code
如果您确实需要杀死子任务的能力,请使用替代实现。
多处理
和gevent
均支持杀死“线程”。Python的线程不支持取消。甚至不要尝试。您的代码很可能发生死锁,损坏或泄漏记忆,或者具有很少和非确定性发生的其他意想不到的“有趣”的难以删除的效果。
If you really need the ability to kill a sub-task, use an alternate implementation.
multiprocessing
andgevent
both support indiscriminately killing a "thread".Python's threading does not support cancellation. Do not even try. Your code is very likely to deadlock, corrupt or leak memory, or have other unintended "interesting" hard-to-debug effects which happen rarely and nondeterministically.
PIETER HINTJENS- ØMQ -project--避免使用锁,静音,事件等诸如锁定的原始词,这是编写多线程程序的清晰和最新方法:
http://zguide.zeromq.org/py:all#multithreading-with-zeromq
这包括告诉孩子线程,它应该取消其工作。这是通过将线程配备Ømq插座和在该插座上进行轮询的消息来完成的,以获取一条消息,说它应该取消。
该链接还提供了带有Ømq的多线程Python代码的示例。
Pieter Hintjens -- one of the founders of the ØMQ-project -- says, using ØMQ and avoiding synchronization primitives like locks, mutexes, events etc., is the sanest and securest way to write multi-threaded programs:
http://zguide.zeromq.org/py:all#Multithreading-with-ZeroMQ
This includes telling a child thread, that it should cancel its work. This would be done by equipping the thread with a ØMQ-socket and polling on that socket for a message saying that it should cancel.
The link also provides an example on multi-threaded python code with ØMQ.
这似乎与Windows 7上的Pywin32一起使用
This seems to work with pywin32 on windows 7
您可以在过程中执行命令,然后使用进程ID杀死它。
我需要在两个线程之间同步,其中一个线程不会单独返回。
You can execute your command in a process and then kill it using the process id.
I needed to sync between two thread one of which doesn’t return by itself.
这是做到这一点的方法:
给它几秒钟,然后您的线程应停止。还检查
thread._thread__delete()
方法。为了方便起见,我将建议使用
thread.quit()
方法。例如,如果线程中有一个套接字,我建议您在套接字处理类中创建一个Quit()
方法,终止套接字,然后运行thread._thread__stop()
在您的Quit()
的内部。Here's how to do it:
Give it a few seconds then your thread should be stopped. Check also the
thread._Thread__delete()
method.I'd recommend a
thread.quit()
method for convenience. For example if you have a socket in your thread, I'd recommend creating aquit()
method in your socket-handle class, terminate the socket, then run athread._Thread__stop()
inside of yourquit()
.使用setDaemon(true)启动子线程。
Start the sub thread with setDaemon(True).