标签归档:terminate

如何停止/终止python脚本的运行?

问题:如何停止/终止python脚本的运行?

我用IDLE编写了一个程序来标记文本文件,然后开始标记349个文本文件!我该如何阻止它?如何停止正在运行的Python程序?

I wrote a program in IDLE to tokenize text files and it starts to tokeniza 349 text files! How can I stop it? How can I stop a running Python program?


回答 0

要停止程序,只需按Control + C

To stop your program, just press Control + C.


回答 1

如果exit()在代码中使用该函数,也可以执行此操作。更理想的是,您可以这样做sys.exit()。即使您通过软件包并行运行程序sys.exit()也可能终止Python multiprocessing

注意:为了使用sys.exit(),您必须将其导入:import sys

You can also do it if you use the exit() function in your code. More ideally, you can do sys.exit(). sys.exit() which might terminate Python even if you are running things in parallel through the multiprocessing package.

Note: In order to use the sys.exit(), you must import it: import sys


回答 2

如果您的程序在交互式控制台上运行,则按CTRL+CKeyboardInterrupt在主线程上引发异常。

如果您的Python程序没有捕获到它,KeyboardInterrupt则会导致Python退出。但是,一个except KeyboardInterrupt:块或类似裸露的东西except:将阻止此机制实际停止脚本的运行。

有时,如果KeyboardInterrupt无法正常工作,您可以发送SIGBREAK信号。在Windows上,解释器可以处理CTRL+Pause/Break而不生成可捕获的KeyboardInterrupt异常。

但是,这些机制主要仅在Python解释器正在运行并响应操作系统事件时才起作用。如果Python解释器由于某种原因没有响应,则最有效的方法是终止运行解释器的整个操作系统进程。其机制因操作系统而异。

在Unix风格的shell环境,您可以按CTRL+Z中止任何进程当前控制的控制台。返回shell提示后,您可以使用jobs它列出挂起的作业,并可以使用杀死第一个挂起的作业kill %1。(如果要重新开始运行,可以使用fg %1;在前台继续执行作业;有关更多信息,请阅读Shell的作业控制手册。)

另外,在Unix或类似Unix的环境中,您可以找到Python进程的PID(进程标识符)并用PID杀死它。使用类似的方法ps aux | grep python来查找正在运行的Python进程,然后使用kill <pid>发送SIGTERM信号。

killUnix上的命令SIGTERM默认发送,Python程序可以安装信号处理程序以SIGTERM使用该signal模块。从理论上讲,任何用于的信号处理程序SIGTERM都应正常关闭进程。但是有时,如果进程卡住了(例如,在不间断的IO睡眠状态下被阻塞),则SIGTERM信号无效,因为该进程甚至无法唤醒以处理该信号。

为了强行终止不响应信号的进程,您需要发送SIGKILL信号,有时称为,kill -9因为它9SIGKILL常量的数值。在命令行中,您可以使用kill -KILL <pid>(或kill -9 <pid>简称)发送aSIGKILL并立即停止该进程运行。

在Windows上,您没有Unix的进程信号系统,但是您可以使用TerminateProcess函数强制终止正在运行的进程。以交互方式,最简单的方法是打开任务管理器,找到python.exe与您的程序相对应的进程,然后单击“结束进程”按钮。您也可以将taskkill命令用于类似目的。

If your program is running at an interactive console, pressing CTRL + C will raise a KeyboardInterrupt exception on the main thread.

If your Python program doesn’t catch it, the KeyboardInterrupt will cause Python to exit. However, an except KeyboardInterrupt: block, or something like a bare except:, will prevent this mechanism from actually stopping the script from running.

Sometimes if KeyboardInterrupt is not working you can send a SIGBREAK signal instead; on Windows, CTRL + Pause/Break may be handled by the interpreter without generating a catchable KeyboardInterrupt exception.

However, these mechanisms mainly only work if the Python interpreter is running and responding to operating system events. If the Python interpreter is not responding for some reason, the most effective way is to terminate the entire operating system process that is running the interpreter. The mechanism for this varies by operating system.

In a Unix-style shell environment, you can press CTRL + Z to suspend whatever process is currently controlling the console. Once you get the shell prompt back, you can use jobs to list suspended jobs, and you can kill the first suspended job with kill %1. (If you want to start it running again, you can continue the job in the foreground by using fg %1; read your shell’s manual on job control for more information.)

Alternatively, in a Unix or Unix-like environment, you can find the Python process’s PID (process identifier) and kill it by PID. Use something like ps aux | grep python to find which Python processes are running, and then use kill <pid> to send a SIGTERM signal.

The kill command on Unix sends SIGTERM by default, and a Python program can install a signal handler for SIGTERM using the signal module. In theory, any signal handler for SIGTERM should shut down the process gracefully. But sometimes if the process is stuck (for example, blocked in an uninterruptable IO sleep state), a SIGTERM signal has no effect because the process can’t even wake up to handle it.

To forcibly kill a process that isn’t responding to signals, you need to send the SIGKILL signal, sometimes referred to as kill -9 because 9 is the numeric value of the SIGKILL constant. From the command line, you can use kill -KILL <pid> (or kill -9 <pid> for short) to send a SIGKILL and stop the process running immediately.

On Windows, you don’t have the Unix system of process signals, but you can forcibly terminate a running process by using the TerminateProcess function. Interactively, the easiest way to do this is to open Task Manager, find the python.exe process that corresponds to your program, and click the “End Process” button. You can also use the taskkill command for similar purposes.


回答 3

  • 要停止python脚本,只需按Ctrl + C
  • 在脚本中exit(),您可以执行此操作。
  • 您可以在退出后的交互式脚本中进行操作。
  • 您可以使用pkill -f name-of-the-python-script
  • To stop a python script just press Ctrl + C.
  • Inside a script with exit(), you can do it.
  • You can do it in an interactive script with just exit.
  • You can use pkill -f name-of-the-python-script.

回答 4

Ctrl-BreakCtrl-C更强大

Ctrl-Break it is more powerful than Ctrl-C


回答 5

要停止正在运行的程序,请使用Ctrl+C终止该过程。

要在python中以编程方式处理它,请导入sys模块并sys.exit()在要终止程序的位置使用。

import sys
sys.exit()

To stop a running program, use Ctrl+C to terminate the process.

To handle it programmatically in python, import the sys module and use sys.exit() where you want to terminate the program.

import sys
sys.exit()

回答 6

要使用键盘停止python脚本,请执行以下操作:Ctrl+C

使用代码停止它(这在Python 3上对我有用):

import os
os._exit(0)

您还可以使用:

import sys
sys.exit()

要么:

exit()

要么:

raise SystemExit

To stop a python script using the keyboard: Ctrl + C

To stop it using code (This has worked for me on Python 3) :

import os
os._exit(0)

you can also use:

import sys
sys.exit()

or:

exit()

or:

raise SystemExit

回答 7

如果您陷入python shell中,请按Ctrl +Z。请记住,脚本实例可以在后台继续运行,因此在Linux下,您必须终止相应的进程。

Ctrl + Z should do it, if you’re caught in the python shell. Keep in mind that instances of the script could continue running in background, so under linux you have to kill the corresponding process.


回答 8

当我在Linux终端上运行python脚本时,CTRL + \起作用。(不是CRTL + C或D)

When I have a python script running on a linux terminal, CTRL + \ works. (not CRTL + C or D)


回答 9

Control+D在Windows 10上对我有效。此外,放在exit()末尾也适用。

Control+D works for me on Windows 10. Also, putting exit() at the end also works.


回答 10

如果您在Jupyter Notebook中,则exit()会杀死内核,所以这不是一个好主意。raise命令将停止程序。

exit() will kill the Kernel if you’re in Jupyter Notebook so it’s not a good idea. raise command will stop the program.


回答 11

您还可以使用Activity Monitor停止py进程

you can also use the Activity Monitor to stop the py process


回答 12

要停止程序,只需按CTRL+D

exit()

To stop your program, just press CTRL + D

or exit().


回答 13

Ctrl+ Alt+ Delete,将弹出任务管理器。找到正在运行的Python命令,右键单击它,然后单击“停止”或“杀死”。

Press Ctrl+Alt+Delete and Task Manager will pop up. Find the Python command running, right click on it and and click Stop or Kill.


回答 14

如果您正在使用Spyder,请使用CTRL +。 (DOT),您将重新启动内核,也将停止程序。

If you are working with Spyder, use CTRL + . (DOT) and you will restart the kernel, also you will stop the program.


回答 15

Windows解决方案:Control + C

Macbook解决方案:Control (^) + C

另一种方法是打开一个终端,键入top,记下PID您想杀死的进程,然后在终端上键入:kill -9 <pid>

Windows solution: Control + C.

Macbook solution: Control (^) + C.

Another way is to open a terminal, type top, write down the PID of the process that you would like to kill and then type on the terminal: kill -9 <pid>


有什么办法可以杀死线程吗?

问题:有什么办法可以杀死线程吗?

是否可以在不设置/检查任何标志/信号灯/等的情况下终止正在运行的线程?

Is it possible to terminate a running thread without setting/checking any flags/semaphores/etc.?


回答 0

用Python和任何语言突然终止线程通常是一个错误的模式。考虑以下情况:

  • 线程持有必须正确关闭的关键资源
  • 该线程创建了其他几个必须同时终止的线程。

如果您负担得起的话(如果您要管理自己的线程),处理此问题的一种好方法是有一个exit_request标志,每个线程定期检查一次,以查看是否该退出。

例如:

import threading

class StoppableThread(threading.Thread):
    """Thread class with a stop() method. The thread itself has to check
    regularly for the stopped() condition."""

    def __init__(self,  *args, **kwargs):
        super(StoppableThread, self).__init__(*args, **kwargs)
        self._stop_event = threading.Event()

    def stop(self):
        self._stop_event.set()

    def stopped(self):
        return self._stop_event.is_set()

在此代码中,您应该stop()在希望退出线程时调用该线程,然后使用来等待线程正确退出join()。线程应定期检查停止标志。

但是,在某些情况下,您确实需要杀死线程。一个示例是当您包装一个忙于长时间调用的外部库并且想要中断它时。

以下代码允许(有一些限制)在Python线程中引发Exception:

def _async_raise(tid, exctype):
    '''Raises an exception in the threads with id tid'''
    if not inspect.isclass(exctype):
        raise TypeError("Only types can be raised (not instances)")
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid),
                                                     ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # "if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"
        ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), None)
        raise SystemError("PyThreadState_SetAsyncExc failed")

class ThreadWithExc(threading.Thread):
    '''A thread class that supports raising exception in the thread from
       another thread.
    '''
    def _get_my_tid(self):
        """determines this (self's) thread id

        CAREFUL : this function is executed in the context of the caller
        thread, to get the identity of the thread represented by this
        instance.
        """
        if not self.isAlive():
            raise threading.ThreadError("the thread is not active")

        # do we have it cached?
        if hasattr(self, "_thread_id"):
            return self._thread_id

        # no, look for it in the _active dict
        for tid, tobj in threading._active.items():
            if tobj is self:
                self._thread_id = tid
                return tid

        # TODO: in python 2.6, there's a simpler way to do : self.ident

        raise AssertionError("could not determine the thread's id")

    def raiseExc(self, exctype):
        """Raises the given exception type in the context of this thread.

        If the thread is busy in a system call (time.sleep(),
        socket.accept(), ...), the exception is simply ignored.

        If you are sure that your exception should terminate the thread,
        one way to ensure that it works is:

            t = ThreadWithExc( ... )
            ...
            t.raiseExc( SomeException )
            while t.isAlive():
                time.sleep( 0.1 )
                t.raiseExc( SomeException )

        If the exception is to be caught by the thread, you need a way to
        check that your thread has caught it.

        CAREFUL : this function is executed in the context of the
        caller thread, to raise an excpetion in the context of the
        thread represented by this instance.
        """
        _async_raise( self._get_my_tid(), exctype )

(基于Tomer Filiba的Killable Threads。有关return值的引用PyThreadState_SetAsyncExc似乎来自旧版本的Python。)

如文档中所述,这不是灵丹妙药,因为如果线程在Python解释器之外很忙,它将无法捕获中断。

此代码的一个很好的用法模式是让线程捕获特定的异常并执行清理。这样,您可以中断任务并仍然进行适当的清理。

It is generally a bad pattern to kill a thread abruptly, in Python and in any language. Think of the following cases:

  • the thread is holding a critical resource that must be closed properly
  • the thread has created several other threads that must be killed as well.

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 threads checks on regular interval to see if it is time for it to exit.

For example:

import threading

class StoppableThread(threading.Thread):
    """Thread class with a stop() method. The thread itself has to check
    regularly for the stopped() condition."""

    def __init__(self,  *args, **kwargs):
        super(StoppableThread, self).__init__(*args, **kwargs)
        self._stop_event = threading.Event()

    def stop(self):
        self._stop_event.set()

    def stopped(self):
        return self._stop_event.is_set()

In this code, you should call stop() on the thread when you want it to exit, and wait for the thread to exit properly using join(). 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:

def _async_raise(tid, exctype):
    '''Raises an exception in the threads with id tid'''
    if not inspect.isclass(exctype):
        raise TypeError("Only types can be raised (not instances)")
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid),
                                                     ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # "if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"
        ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), None)
        raise SystemError("PyThreadState_SetAsyncExc failed")

class ThreadWithExc(threading.Thread):
    '''A thread class that supports raising exception in the thread from
       another thread.
    '''
    def _get_my_tid(self):
        """determines this (self's) thread id

        CAREFUL : this function is executed in the context of the caller
        thread, to get the identity of the thread represented by this
        instance.
        """
        if not self.isAlive():
            raise threading.ThreadError("the thread is not active")

        # do we have it cached?
        if hasattr(self, "_thread_id"):
            return self._thread_id

        # no, look for it in the _active dict
        for tid, tobj in threading._active.items():
            if tobj is self:
                self._thread_id = tid
                return tid

        # TODO: in python 2.6, there's a simpler way to do : self.ident

        raise AssertionError("could not determine the thread's id")

    def raiseExc(self, exctype):
        """Raises the given exception type in the context of this thread.

        If the thread is busy in a system call (time.sleep(),
        socket.accept(), ...), the exception is simply ignored.

        If you are sure that your exception should terminate the thread,
        one way to ensure that it works is:

            t = ThreadWithExc( ... )
            ...
            t.raiseExc( SomeException )
            while t.isAlive():
                time.sleep( 0.1 )
                t.raiseExc( SomeException )

        If the exception is to be caught by the thread, you need a way to
        check that your thread has caught it.

        CAREFUL : this function is executed in the context of the
        caller thread, to raise an excpetion in the context of the
        thread represented by this instance.
        """
        _async_raise( self._get_my_tid(), exctype )

(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.


回答 1

没有官方的API可以这样做。

您需要使用平台API杀死线程,例如pthread_kill或TerminateThread。您可以通过pythonwin或ctypes访问此类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.


回答 2

一个multiprocessing.Process罐头p.terminate()

在我想杀死一个线程,但又不想使用标志/锁/信号/信号量/事件/任何东西的情况下,我会将线程提升为完整进程。对于仅使用几个线程的代码,开销并不是那么糟糕。

例如,这样做很方便,可以轻松终止执行阻塞I / O的助手“线程”

转换是微不足道的:在相关代码中,将全部替换threading.Threadmultiprocessing.Process和全部替换queue.Queuemultiprocessing.Queue,并将所需的调用添加p.terminate()到要杀死其子级的父进程中p

请参阅Python文档multiprocessing

A multiprocessing.Process can p.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 with multiprocessing.Process and all queue.Queue with multiprocessing.Queue and add the required calls of p.terminate() to your parent process which wants to kill its child p

See the Python documentation for multiprocessing.


回答 3

如果试图终止整个程序,则可以将线程设置为“守护程序”。参见 Thread.daemon

If you are trying to terminate the whole program you can set the thread as a “daemon”. see Thread.daemon


回答 4

正如其他人提到的那样,规范是设置停止标志。对于轻量级的东西(没有Thread的子类,没有全局变量),可以选择使用lambda回调。(请注意中的括号if stop()。)

import threading
import time

def do_work(id, stop):
    print("I am thread", id)
    while True:
        print("I am thread {} doing something".format(id))
        if stop():
            print("  Exiting loop.")
            break
    print("Thread {}, signing off".format(id))


def main():
    stop_threads = False
    workers = []
    for id in range(0,3):
        tmp = threading.Thread(target=do_work, args=(id, lambda: stop_threads))
        workers.append(tmp)
        tmp.start()
    time.sleep(3)
    print('main: done sleeping; time to stop the threads.')
    stop_threads = True
    for worker in workers:
        worker.join()
    print('Finis.')

if __name__ == '__main__':
    main()

替换print()pr()始终刷新(sys.stdout.flush())的函数可以提高Shell输出的精度。

(仅在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().)

import threading
import time

def do_work(id, stop):
    print("I am thread", id)
    while True:
        print("I am thread {} doing something".format(id))
        if stop():
            print("  Exiting loop.")
            break
    print("Thread {}, signing off".format(id))


def main():
    stop_threads = False
    workers = []
    for id in range(0,3):
        tmp = threading.Thread(target=do_work, args=(id, lambda: stop_threads))
        workers.append(tmp)
        tmp.start()
    time.sleep(3)
    print('main: done sleeping; time to stop the threads.')
    stop_threads = True
    for worker in workers:
        worker.join()
    print('Finis.')

if __name__ == '__main__':
    main()

Replacing print() with a pr() function that always flushes (sys.stdout.flush()) may improve the precision of the shell output.

(Only tested on Windows/Eclipse/Python3.3)


回答 5

这基于thread2-可杀死的线程(Python配方)

您需要调用PyThreadState_SetasyncExc(),该方法仅可通过ctypes使用。

该功能仅在Python 2.7.3上进行了测试,但可能与其他最新的2.x版本一起使用。

import ctypes

def terminate_thread(thread):
    """Terminates a python thread from another thread.

    :param thread: a threading.Thread instance
    """
    if not thread.isAlive():
        return

    exc = ctypes.py_object(SystemExit)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
        ctypes.c_long(thread.ident), exc)
    if res == 0:
        raise ValueError("nonexistent thread id")
    elif res > 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")

This is based on thread2 — killable threads (Python recipe)

You need to call PyThreadState_SetasyncExc(), which is only available through ctypes.

This has only been tested on Python 2.7.3, but it is likely to work with other recent 2.x releases.

import ctypes

def terminate_thread(thread):
    """Terminates a python thread from another thread.

    :param thread: a threading.Thread instance
    """
    if not thread.isAlive():
        return

    exc = ctypes.py_object(SystemExit)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
        ctypes.c_long(thread.ident), exc)
    if res == 0:
        raise ValueError("nonexistent thread id")
    elif res > 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")

回答 6

如果不配合使用线程,切勿强行杀死它。

杀死线程会删除所有尝试/最终阻止设置的保证,因此您可能会锁定锁,打开文件等。

唯一可以断言强行杀死线程是个好主意的方法是快速杀死程序,但绝不要杀死单个线程。

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.


回答 7

在Python中,您根本无法直接杀死线程。

如果您实际上并不需要Thread(!),则可以使用 multiprocessing软件包,而不是使用threading软件包来做。在这里,要杀死一个进程,您可以简单地调用方法:

yourProcess.terminate()  # kill the process!

Python将杀死您的进程(在Unix上通过SIGTERM信号,而在Windows上通过TerminateProcess()调用)。在使用队列或管道时,请注意使用它!(它可能会损坏队列/管道中的数据)

请注意,multiprocessing.Event和的multiprocessing.Semaphore工作方式与threading.Event和的完全相同threading.Semaphore。实际上,第一个是后者的克隆。

如果您确实需要使用线程,则无法直接杀死它。但是,您可以使用“守护程序线程”。实际上,在Python中,可以将Thread标记为守护程序

yourThread.daemon = True  # set the Thread as a "daemon thread"

当没有活动的非守护线程时,主程序将退出。换句话说,当您的主线程(当然,这是一个非守护程序线程)完成其操作时,即使仍有一些守护程序线程在工作,程序也会退出。

请注意,有必要daemonstart()调用该方法之前设置一个线程!

当然,daemon甚至可以使用multiprocessing。在这里,当主进程退出时,它将尝试终止其所有守护进程。

最后,请注意,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:

yourProcess.terminate()  # kill the process!

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 the multiprocessing.Semaphore work exactly in the same way of the threading.Event and the threading.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:

yourThread.daemon = True  # set the Thread as a "daemon thread"

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 the start() method is called!

Of course you can, and should, use daemon even with multiprocessing. Here, when the main process exits, it attempts to terminate all of its daemonic child processes.

Finally, please, note that sys.exit() and os.kill() are not choices.


回答 8

您可以通过在将退出线程的线程中安装跟踪来杀死线程。请参阅附件链接以获取一种可能的实现。

在Python中杀死线程

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


回答 9

如果你是显式调用time.sleep()为你的线程(比如查询一些外部的服务)的一部分,在菲利普的方法的改进是使用了超时的eventwait()方法,无论你sleep()

例如:

import threading

class KillableThread(threading.Thread):
    def __init__(self, sleep_interval=1):
        super().__init__()
        self._kill = threading.Event()
        self._interval = sleep_interval

    def run(self):
        while True:
            print("Do Something")

            # If no kill signal is set, sleep for the interval,
            # If kill signal comes in while sleeping, immediately
            #  wake up and handle
            is_killed = self._kill.wait(self._interval)
            if is_killed:
                break

        print("Killing Thread")

    def kill(self):
        self._kill.set()

然后运行

t = KillableThread(sleep_interval=5)
t.start()
# Every 5 seconds it prints:
#: Do Something
t.kill()
#: Killing Thread

使用wait()而不是sleep()ing并定期检查事件的优点是您可以在更长的睡眠间隔内进行编程,线程几乎立即停止(原本应该是sleep()ing),并且我认为处理退出的代码明显更简单。

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 the event‘s wait() method wherever you sleep()

For example:

import threading

class KillableThread(threading.Thread):
    def __init__(self, sleep_interval=1):
        super().__init__()
        self._kill = threading.Event()
        self._interval = sleep_interval

    def run(self):
        while True:
            print("Do Something")

            # If no kill signal is set, sleep for the interval,
            # If kill signal comes in while sleeping, immediately
            #  wake up and handle
            is_killed = self._kill.wait(self._interval)
            if is_killed:
                break

        print("Killing Thread")

    def kill(self):
        self._kill.set()

Then to run it

t = KillableThread(sleep_interval=5)
t.start()
# Every 5 seconds it prints:
#: Do Something
t.kill()
#: Killing Thread

The advantage of using wait() instead of sleep()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 be sleep()ing) and in my opinion, the code for handling exit is significantly simpler.


回答 10

如果您不杀死线程,那就更好了。一种方法可能是在线程的循环中引入“ try”块,并在您要停止线程时引发异常(例如,break / return / …会停止for / 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…


回答 11

绝对有可能实现Thread.stop以下示例代码中所示的方法:

import sys
import threading
import time


class StopThread(StopIteration):
    pass

threading.SystemExit = SystemExit, StopThread


class Thread2(threading.Thread):

    def stop(self):
        self.__stop = True

    def _bootstrap(self):
        if threading._trace_hook is not None:
            raise ValueError('Cannot run thread with tracing!')
        self.__stop = False
        sys.settrace(self.__trace)
        super()._bootstrap()

    def __trace(self, frame, event, arg):
        if self.__stop:
            raise StopThread()
        return self.__trace


class Thread3(threading.Thread):

    def _bootstrap(self, stop_thread=False):
        def stop():
            nonlocal stop_thread
            stop_thread = True
        self.stop = stop

        def tracer(*_):
            if stop_thread:
                raise StopThread()
            return tracer
        sys.settrace(tracer)
        super()._bootstrap()

###############################################################################


def main():
    test1 = Thread2(target=printer)
    test1.start()
    time.sleep(1)
    test1.stop()
    test1.join()
    test2 = Thread2(target=speed_test)
    test2.start()
    time.sleep(1)
    test2.stop()
    test2.join()
    test3 = Thread3(target=speed_test)
    test3.start()
    time.sleep(1)
    test3.stop()
    test3.join()


def printer():
    while True:
        print(time.time() % 1)
        time.sleep(0.1)


def speed_test(count=0):
    try:
        while True:
            count += 1
    except StopThread:
        print('Count =', count)

if __name__ == '__main__':
    main()

Thread3类似乎比快大约33%的运行代码Thread2类。

It is definitely possible to implement a Thread.stop method as shown in the following example code:

import sys
import threading
import time


class StopThread(StopIteration):
    pass

threading.SystemExit = SystemExit, StopThread


class Thread2(threading.Thread):

    def stop(self):
        self.__stop = True

    def _bootstrap(self):
        if threading._trace_hook is not None:
            raise ValueError('Cannot run thread with tracing!')
        self.__stop = False
        sys.settrace(self.__trace)
        super()._bootstrap()

    def __trace(self, frame, event, arg):
        if self.__stop:
            raise StopThread()
        return self.__trace


class Thread3(threading.Thread):

    def _bootstrap(self, stop_thread=False):
        def stop():
            nonlocal stop_thread
            stop_thread = True
        self.stop = stop

        def tracer(*_):
            if stop_thread:
                raise StopThread()
            return tracer
        sys.settrace(tracer)
        super()._bootstrap()

###############################################################################


def main():
    test1 = Thread2(target=printer)
    test1.start()
    time.sleep(1)
    test1.stop()
    test1.join()
    test2 = Thread2(target=speed_test)
    test2.start()
    time.sleep(1)
    test2.stop()
    test2.join()
    test3 = Thread3(target=speed_test)
    test3.start()
    time.sleep(1)
    test3.stop()
    test3.join()


def printer():
    while True:
        print(time.time() % 1)
        time.sleep(0.1)


def speed_test(count=0):
    try:
        while True:
            count += 1
    except StopThread:
        print('Count =', count)

if __name__ == '__main__':
    main()

The Thread3 class appears to run code approximately 33% faster than the Thread2 class.


回答 12

from ctypes import *
pthread = cdll.LoadLibrary("libpthread-2.15.so")
pthread.pthread_cancel(c_ulong(t.ident))

t是您的Thread对象。

阅读python源代码(Modules/threadmodule.cPython/thread_pthread.h),您可以看到的Thread.ident是一种pthread_t类型,因此您可以pthread在python use中做任何事情libpthread

from ctypes import *
pthread = cdll.LoadLibrary("libpthread-2.15.so")
pthread.pthread_cancel(c_ulong(t.ident))

t is your Thread object.

Read the python source (Modules/threadmodule.c and Python/thread_pthread.h) you can see the Thread.ident is an pthread_t type, so you can do anything pthread can do in python use libpthread.


回答 13

可以使用以下解决方法杀死线程:

kill_threads = False

def doSomething():
    global kill_threads
    while True:
        if kill_threads:
            thread.exit()
        ......
        ......

thread.start_new_thread(doSomething, ())

这甚至可以用于终止从主线程终止其代码在另一个模块中编写的线程。我们可以在该模块中声明一个全局变量,并使用它终止该模块中产生的线程。

我通常使用它在程序出口处终止所有线程。这可能不是终止线程的理想方法,但可能会有所帮助。

Following workaround can be used to kill a thread:

kill_threads = False

def doSomething():
    global kill_threads
    while True:
        if kill_threads:
            thread.exit()
        ......
        ......

thread.start_new_thread(doSomething, ())

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.


回答 14

我玩这个游戏很晚,但是我一直在努力解决类似的问题,以下内容似乎可以为我很好地解决问题,并且让守护子线程退出时让我做一些基本的线程状态检查和清理工作:

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()

Yield:

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

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:

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()

Yields:

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

回答 15

我想补充的一件事是,如果您在线程lib Python中阅读了官方文档,建议您避免使用“恶魔”线程,如果您不希望线程突然结束,请使用Paolo Rovelli 提到的标志。

根据官方文档:

守护程序线程在关闭时突然停止。它们的资源(例如打开的文件,数据库事务等)可能无法正确释放。如果您希望线程正常停止,请将它们设置为非守护进程,并使用适当的信令机制(例如事件)。

我认为创建守护线程取决于您的应用程序,但总的来说(我认为)最好避免杀死它们或使其成为守护线程。在多处理中,您可以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:

Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signaling mechanism such as an Event.

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).


回答 16

有一个为此目的而建立的库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.


回答 17

虽然它已经很老了,对于某些人来说可能是一个方便的解决方案:

一个扩展了线程的模块功能的小模块-允许一个线程在另一个线程的上下文中引发异常。通过提高SystemExit,您最终可以杀死python线程。

import threading
import ctypes     

def _async_raise(tid, excobj):
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(excobj))
    if res == 0:
        raise ValueError("nonexistent thread id")
    elif res > 1:
        # """if it returns a number greater than one, you're in trouble, 
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
        raise SystemError("PyThreadState_SetAsyncExc failed")

class Thread(threading.Thread):
    def raise_exc(self, excobj):
        assert self.isAlive(), "thread must be started"
        for tid, tobj in threading._active.items():
            if tobj is self:
                _async_raise(tid, excobj)
                return

        # the thread was alive when we entered the loop, but was not found 
        # in the dict, hence it must have been already terminated. should we raise
        # an exception here? silently ignore?

    def terminate(self):
        # must raise the SystemExit type, instead of a SystemExit() instance
        # due to a bug in PyThreadState_SetAsyncExc
        self.raise_exc(SystemExit)

因此,它允许“线程在另一个线程的上下文中引发异常”,这样,终止的线程可以处理终止,而无需定期检查中止标志。

但是,根据其原始来源,此代码存在一些问题。

  • 仅在执行python字节码时才会引发异常。如果您的线程调用了本机/内置阻止函数,则仅当执行返回到python代码时才会引发异常。
    • 如果内置函数在内部调用PyErr_Clear()也会存在一个问题,这将有效地取消您的未决异常。您可以尝试再次提高它。
  • 只有异常类型可以安全地引发。异常实例可能会导致意外行为,因此受到限制。
  • 我要求在内置线程模块中公开此功能,但是由于ctypes已成为标准库(从2.5版开始),并且此
    功能不太可能与实现无关,因此可以不公开

While it’s rather old, this might be a handy solution for some:

A little module that extends the threading’s module functionality — allows one thread to raise exceptions in the context of another thread. By raising SystemExit, you can finally kill python threads.

import threading
import ctypes     

def _async_raise(tid, excobj):
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(excobj))
    if res == 0:
        raise ValueError("nonexistent thread id")
    elif res > 1:
        # """if it returns a number greater than one, you're in trouble, 
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
        raise SystemError("PyThreadState_SetAsyncExc failed")

class Thread(threading.Thread):
    def raise_exc(self, excobj):
        assert self.isAlive(), "thread must be started"
        for tid, tobj in threading._active.items():
            if tobj is self:
                _async_raise(tid, excobj)
                return

        # the thread was alive when we entered the loop, but was not found 
        # in the dict, hence it must have been already terminated. should we raise
        # an exception here? silently ignore?

    def terminate(self):
        # must raise the SystemExit type, instead of a SystemExit() instance
        # due to a bug in PyThreadState_SetAsyncExc
        self.raise_exc(SystemExit)

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.

  • The exception will be raised only when executing python bytecode. If your thread calls a native/built-in blocking function, the exception will be raised only when execution returns to the python code.
    • There is also an issue if the built-in function internally calls PyErr_Clear(), which would effectively cancel your pending exception. You can try to raise it again.
  • Only exception types can be raised safely. Exception instances are likely to cause unexpected behavior, and are thus restricted.
  • I asked to expose this function in the built-in thread module, but since ctypes has become a standard library (as of 2.5), and this
    feature is not likely to be implementation-agnostic, it may be kept
    unexposed.

回答 18

这似乎与Windows 7上的pywin32一起使用

my_thread = threading.Thread()
my_thread.start()
my_thread._Thread__stop()

This seems to work with pywin32 on windows 7

my_thread = threading.Thread()
my_thread.start()
my_thread._Thread__stop()

回答 19

ØMQ项目的创始人之一Pieter Hintjens 说,使用ØMQ并避免使用同步原语(例如锁,互斥体,事件等),是编写多线程程序的最安全的方法:

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.


回答 20

假设您要具有多个具有相同功能的线程,这是恕我直言,最简单的实现是通过id停止一个线程:

import time
from threading import Thread

def doit(id=0):
    doit.stop=0
    print("start id:%d"%id)
    while 1:
        time.sleep(1)
        print(".")
        if doit.stop==id:
            doit.stop=0
            break
    print("end thread %d"%id)

t5=Thread(target=doit, args=(5,))
t6=Thread(target=doit, args=(6,))

t5.start() ; t6.start()
time.sleep(2)
doit.stop =5  #kill t5
time.sleep(2)
doit.stop =6  #kill t6

不错的是,您可以拥有多个相同和不同的功能,并通过以下方式将其全部停止 functionname.stop

如果您只想使用该函数的一个线程,则无需记住ID。如果doit.stop> 0 ,则停止。

Asuming, that you want to have multiple threads of the same function, this is IMHO the easiest implementation to stop one by id:

import time
from threading import Thread

def doit(id=0):
    doit.stop=0
    print("start id:%d"%id)
    while 1:
        time.sleep(1)
        print(".")
        if doit.stop==id:
            doit.stop=0
            break
    print("end thread %d"%id)

t5=Thread(target=doit, args=(5,))
t6=Thread(target=doit, args=(6,))

t5.start() ; t6.start()
time.sleep(2)
doit.stop =5  #kill t5
time.sleep(2)
doit.stop =6  #kill t6

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.


回答 21

只是基于@SCB的想法(这正是我所需要的)来创建具有自定义函数的KillableThread子类:

from threading import Thread, Event

class KillableThread(Thread):
    def __init__(self, sleep_interval=1, target=None, name=None, args=(), kwargs={}):
        super().__init__(None, target, name, args, kwargs)
        self._kill = Event()
        self._interval = sleep_interval
        print(self._target)

    def run(self):
        while True:
            # Call custom function with arguments
            self._target(*self._args)

        # If no kill signal is set, sleep for the interval,
        # If kill signal comes in while sleeping, immediately
        #  wake up and handle
        is_killed = self._kill.wait(self._interval)
        if is_killed:
            break

    print("Killing Thread")

def kill(self):
    self._kill.set()

if __name__ == '__main__':

    def print_msg(msg):
        print(msg)

    t = KillableThread(10, print_msg, args=("hello world"))
    t.start()
    time.sleep(6)
    print("About to kill thread")
    t.kill()

自然,就像@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:

from threading import Thread, Event

class KillableThread(Thread):
    def __init__(self, sleep_interval=1, target=None, name=None, args=(), kwargs={}):
        super().__init__(None, target, name, args, kwargs)
        self._kill = Event()
        self._interval = sleep_interval
        print(self._target)

    def run(self):
        while True:
            # Call custom function with arguments
            self._target(*self._args)

        # If no kill signal is set, sleep for the interval,
        # If kill signal comes in while sleeping, immediately
        #  wake up and handle
        is_killed = self._kill.wait(self._interval)
        if is_killed:
            break

    print("Killing Thread")

def kill(self):
    self._kill.set()

if __name__ == '__main__':

    def print_msg(msg):
        print(msg)

    t = KillableThread(10, print_msg, args=("hello world"))
    t.start()
    time.sleep(6)
    print("About to kill thread")
    t.kill()

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.


回答 22

如@Kozyarchuk的答案中所述,安装跟踪有效。由于此答案不包含任何代码,因此下面是一个可以使用的示例:

import sys, threading, time 

class TraceThread(threading.Thread): 
    def __init__(self, *args, **keywords): 
        threading.Thread.__init__(self, *args, **keywords) 
        self.killed = False
    def start(self): 
        self._run = self.run 
        self.run = self.settrace_and_run
        threading.Thread.start(self) 
    def settrace_and_run(self): 
        sys.settrace(self.globaltrace) 
        self._run()
    def globaltrace(self, frame, event, arg): 
        return self.localtrace if event == 'call' else None
    def localtrace(self, frame, event, arg): 
        if self.killed and event == 'line': 
            raise SystemExit() 
        return self.localtrace 

def f(): 
    while True: 
        print('1') 
        time.sleep(2)
        print('2') 
        time.sleep(2)
        print('3') 
        time.sleep(2)

t = TraceThread(target=f) 
t.start() 
time.sleep(2.5) 
t.killed = True

打印1并打印后停止23不打印。

As mentioned in @Kozyarchuk’s answer, installing trace works. Since this answer contained no code, here is a working ready-to-use example:

import sys, threading, time 

class TraceThread(threading.Thread): 
    def __init__(self, *args, **keywords): 
        threading.Thread.__init__(self, *args, **keywords) 
        self.killed = False
    def start(self): 
        self._run = self.run 
        self.run = self.settrace_and_run
        threading.Thread.start(self) 
    def settrace_and_run(self): 
        sys.settrace(self.globaltrace) 
        self._run()
    def globaltrace(self, frame, event, arg): 
        return self.localtrace if event == 'call' else None
    def localtrace(self, frame, event, arg): 
        if self.killed and event == 'line': 
            raise SystemExit() 
        return self.localtrace 

def f(): 
    while True: 
        print('1') 
        time.sleep(2)
        print('2') 
        time.sleep(2)
        print('3') 
        time.sleep(2)

t = TraceThread(target=f) 
t.start() 
time.sleep(2.5) 
t.killed = True

It stops after having printed 1 and 2. 3 is not printed.


回答 23

您可以在进程中执行命令,然后使用进程ID将其杀死。我需要在两个线程之间进行同步,其中一个线程不会自行返回。

processIds = []

def executeRecord(command):
    print(command)

    process = subprocess.Popen(command, stdout=subprocess.PIPE)
    processIds.append(process.pid)
    print(processIds[0])

    #Command that doesn't return by itself
    process.stdout.read().decode("utf-8")
    return;


def recordThread(command, timeOut):

    thread = Thread(target=executeRecord, args=(command,))
    thread.start()
    thread.join(timeOut)

    os.kill(processIds.pop(), signal.SIGINT)

    return;

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.

processIds = []

def executeRecord(command):
    print(command)

    process = subprocess.Popen(command, stdout=subprocess.PIPE)
    processIds.append(process.pid)
    print(processIds[0])

    #Command that doesn't return by itself
    process.stdout.read().decode("utf-8")
    return;


def recordThread(command, timeOut):

    thread = Thread(target=executeRecord, args=(command,))
    thread.start()
    thread.join(timeOut)

    os.kill(processIds.pop(), signal.SIGINT)

    return;

回答 24

使用setDaemon(True)启动子线程。

def bootstrap(_filename):
    mb = ModelBootstrap(filename=_filename) # Has many Daemon threads. All get stopped automatically when main thread is stopped.

t = threading.Thread(target=bootstrap,args=('models.conf',))
t.setDaemon(False)

while True:
    t.start()
    time.sleep(10) # I am just allowing the sub-thread to run for 10 sec. You can listen on an event to stop execution.
    print('Thread stopped')
    break

Start the sub thread with setDaemon(True).

def bootstrap(_filename):
    mb = ModelBootstrap(filename=_filename) # Has many Daemon threads. All get stopped automatically when main thread is stopped.

t = threading.Thread(target=bootstrap,args=('models.conf',))
t.setDaemon(False)

while True:
    t.start()
    time.sleep(10) # I am just allowing the sub-thread to run for 10 sec. You can listen on an event to stop execution.
    print('Thread stopped')
    break

回答 25

这是一个错误的答案,请参阅评论

方法如下:

from threading import *

...

for thread in enumerate():
    if thread.isAlive():
        try:
            thread._Thread__stop()
        except:
            print(str(thread.getName()) + ' could not be terminated'))

给它几秒钟,然后应该停止线程。还要检查thread._Thread__delete()方法。

thread.quit()为了方便起见,我建议使用一种方法。例如,如果您的线程中有一个套接字,建议quit()您在套接字句柄类中创建一个方法,终止该套接字,然后在的thread._Thread__stop()内部运行quit()

This is a bad answer, see the comments

Here’s how to do it:

from threading import *

...

for thread in enumerate():
    if thread.isAlive():
        try:
            thread._Thread__stop()
        except:
            print(str(thread.getName()) + ' could not be terminated'))

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 a quit() method in your socket-handle class, terminate the socket, then run a thread._Thread__stop() inside of your quit().


回答 26

如果您确实需要杀死子任务的能力,请使用替代实现。multiprocessing并且gevent都支持滥杀“线程”。

Python的线程不支持取消。想都别想。您的代码很可能会死锁,损坏或泄漏内存,或者具有其他意想不到的“有趣”难以调试的效果,这种情况很少且不确定地发生。

If you really need the ability to kill a sub-task, use an alternate implementation. multiprocessing and gevent 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.