[Tut] How To Kill A Thread In Python? - Printable Version +- Sick Gaming (https://www.sickgaming.net) +-- Forum: Programming (https://www.sickgaming.net/forum-76.html) +--- Forum: Python (https://www.sickgaming.net/forum-83.html) +--- Thread: [Tut] How To Kill A Thread In Python? (/thread-97910.html) |
[Tut] How To Kill A Thread In Python? - xSicKxBot - 10-24-2020 How To Kill A Thread In Python? <div><p><strong>Summary: </strong>To kill a thread use one of the following methods:</p> <ul> <li>Create an <strong>Exit_Request</strong> flag.</li> <li>Using the <code>multiprocessing </code>Module.</li> <li>Using the <code>trace </code>Module.</li> <li>Using <code>ctypes </code>to raise Exceptions in a thread</li> </ul> <p><strong>Problem:</strong> <strong>How to<span style="color:#cf2e2e" class="has-inline-color"> kill a thread</span> in Python?</strong></p> <p>This is one of the most commonly asked questions in Python. Thus, in this article, we are going to address this issue and make sure you have a clear understanding of this topic. Before divining into the topic directly, we will have a look at threading in brief and then move on to our mission-critical question. So without further delay, let the games begin! <img src="https://s.w.org/images/core/emoji/13.0.0/72x72/1f60e.png" alt="?" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </p> <h2>Introduction</h2> <p><img src="https://s.w.org/images/core/emoji/13.0.0/72x72/1f9f5.png" alt="?" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>What is a <span style="color:#cf2e2e" class="has-inline-color">Thread</span>?</strong></p> <p>According to <a href="https://en.wikipedia.org/wiki/Thread_(computing)" target="_blank" rel="noreferrer noopener">Wikipedia</a>, <strong>in computer science, a thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler, which is typically a part of the operating system.</strong> Multiple threads can run concurrently within a single program. For example in a word processor, a background thread may be used for spell-checking while a foreground thread may be used to processes user input (keystrokes ), while yet a third thread may be used to load images from the hard drive, and a fourth thread might be busy doing periodic automatic backups of the file being edited. </p> <ul> <li>Therefore, treading in Python is used to run multiple threads that can be tasks or function calls, at the same time. Please note that this doesn’t mean that multiple threads are executed on different CPUs. </li> <li>Python threads do not make the program faster in case it already uses 100 % CPU time. That is probably a part of parallel programming which is not within the scope of this discussion.</li> </ul> <p><strong>Note: </strong>Threading in Python is itself an entire topic of discussion. The purpose of this introduction is to just get you acquainted with the idea of threads. It is highly recommended that you have some understanding of threading in Python before diving into the topic of killing the thread.</p> <p>➥ <strong>When do we use Threading in Python?</strong></p> <p>Threads in Python are used in situations where the execution of a task or function call involves some waiting. An example could be interaction with a service hosted on a webserver. Thus, treading allows Python to execute other code while waiting. </p> <p>➥ <strong>Example:</strong></p> <pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import threading import time print("Printing values from 90 to 100: ") def loop_thread(): for t in range(90, 101): time.sleep(1) print(t) threading.Thread(target=loop_thread).start()</pre> <p><strong>Output:</strong></p> <pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Printing values from 90 to 100: 90 91 92 93 94 95 96 97 98 99 100</pre> <p>Now that have an overview of threads, let us dive into our mission-critical question.</p> <h2>Ways To<span style="color:#ff6900" class="has-inline-color"> Kill A Thread</span> In Python</h2> <p>Simply put, <strong>killing a thread abruptly is a very bad practice unless absolutely required</strong>. Having said that, you might want to kill a thread after a certain duration or after some interrupt. So, instead of closing it forcibly, you can kindly ask the thread to go away after ensuring a proper clean up which means:</p> <ul> <li>The thread you are trying to kill might be holding a critical resource that must be closed properly.</li> <li>The thread might have created several other threads that must be killed as well before the parent thread can be killed.</li> </ul> <p>Let us understand the numerous ways that help us to do that.</p> <h3>Method 1: Creating An <span style="color:#ff6900" class="has-inline-color">Exit Request Flag</span></h3> <p>If you are the manager of your own threads, a nice way of handling thread termination is to create an exit flag that each thread checks at regular intervals to know if it is time for it to exit. </p> <p><strong>Example:</strong></p> <pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import threading import time def thread_foo(stop): while True: print("THREAD STILL RUNNING!") if exit_flag: break exit_flag = False t = threading.Thread(target = thread_foo, args =(lambda : exit_flag, )) t.start() time.sleep(0.1) print('Done sleeping! Time to stop the threads.') exit_flag = True t.join() print('THREAD TERMINATED!')</pre> <p><strong>Output:</strong></p> <figure class="wp-block-image size-large"><img loading="lazy" width="598" height="184" src="https://blog.finxter.com/wp-content/uploads/2020/10/image-192.png" alt="" class="wp-image-15532" srcset="https://blog.finxter.com/wp-content/uploads/2020/10/image-192.png 598w, https://blog.finxter.com/wp-content/uploads/2020/10/image-192-300x92.png 300w, https://blog.finxter.com/wp-content/uploads/2020/10/image-192-150x46.png 150w" sizes="(max-width: 598px) 100vw, 598px" /></figure> <p>In the above example, we created a function that keeps executing the thread until the program encounters the variable <code>exit_flag = True</code>. As soon as that happens, the thread can be killed using the <code>t.join()</code> method. </p> <p>➥ <strong><span style="text-decoration: underline">Note:</span> </strong><code>join()</code> causes the main thread to wait for your thread to finish. In other words, <code>join()</code> acts as a “hold” on the main thread. It ensures that your thread has completed its execution before the main thread can move forward. In a way, it assures a clean and proper termination of your thread.</p> <h3>Method 2: Using The <span style="color:#ff6900" class="has-inline-color">Multiprocessing </span><span style="color:#000000" class="has-inline-color">Module</span></h3> <p>As stated in the Python documentation, <a href="https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing" target="_blank" rel="noreferrer noopener"><code>multiprocessing</code></a> is a package that supports spawning processes using an API similar to the <code>threading</code> module. Also, killing a process is much safer than killing a thread because <strong>threads share global variables and have a dependency, whereas processes are completely independent and exist separate from each other.</strong> The <code>multiprocessing </code>module has the <strong><code><span style="color:#cf2e2e" class="has-inline-color">terminate()</span></code> </strong>function which is used to kill a process. </p> <p>Let us have a look at the following example given below to understand how we can use the <code>multiprocessing </code>module to kill the process.</p> <pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import multiprocessing import time def Child_process(): while True: for i in range (20): print ('Process: ', i) time.sleep(0.05) t = multiprocessing.Process(target = Child_process) t.start() time.sleep(0.5) t.terminate() print("Child Process successfully terminated")</pre> <p><strong>Output:</strong></p> <pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Process: 0 Process: 1 Process: 2 Process: 3 Process: 4 Process: 5 Process: 6 Process: 7 Process: 8 Process: 9 Child Process successfully terminated</pre> <p>In the above example after 0.5 seconds the execution of the <code>Child_process</code> was terminated using the <code>terminate()</code> function. </p> <h3>Method 3: Using The <a href="https://web.archive.org/web/20130503082442/http://mail.python.org/pipermail/python-list/2004-May/281943.html" target="_blank" rel="noreferrer noopener">trace </a>Module</h3> <p>Another approach to kill a thread is to install <code>trace</code> into the thread that will exit the thread. </p> <p>The module given below allows you to kill threads. The class <code>KThread</code> is a drop-in replacement for <code>threading.Thread</code>. It adds the <code>kill()</code> method, which should stop most threads in their tracks.</p> <p><strong>Disclaimer: </strong>The procedure given below has been taken from the following resource: <a href="https://web.archive.org/web/20130503082442/http://mail.python.org/pipermail/python-list/2004-May/281943.html" target="_blank" rel="noreferrer noopener"><span style="text-decoration: underline"><strong>Kill a thread in Python</strong></span></a></p> <p> <img src="https://s.w.org/images/core/emoji/13.0.0/72x72/1f40d.png" alt="?" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <span style="text-decoration: underline"><strong>KThread.py</strong>: A killable Thread implementation</span> </p> <pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import time import sys import trace import threading class KThread(threading.Thread): """A subclass of threading.Thread, with a kill() method.""" def __init__(self, *args, **keywords): threading.Thread.__init__(self, *args, **keywords) self.killed = False def start(self): """Start the thread.""" self.__run_backup = self.run self.run = self.__run threading.Thread.start(self) def __run(self): """Hacked run function, which installs the trace.""" sys.settrace(self.globaltrace) self.__run_backup() self.run = self.__run_backup def globaltrace(self, frame, why, arg): if why == 'call': return self.localtrace else: return None def localtrace(self, frame, why, arg): if self.killed: if why == 'line': raise SystemExit() return self.localtrace def kill(self): self.killed = True # Example Usage #This illustrates running a function in a separate thread. The thread is killed before the function finishes. def func(): print('Function started') for i in range(1,100): print(i) time.sleep(0.2) print('Function finished') A = KThread(target=func) A.start() time.sleep(1) A.kill()</pre> <p><strong>Output:</strong></p> <pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Function started 1 2 3 4 5</pre> <h3>Method 4: Using <span style="color:#ff6900" class="has-inline-color">ctypes </span>To Raise Exceptions In A Thread</h3> <p>In cases when you need to kill a thread forcibly, for example while wrapping an external library that is busy for long calls and you want to interrupt it, you can use <strong>raise_exc()</strong> to raise an arbitrary exception, or call <strong>terminate()</strong> to raise <strong>SystemExit</strong> automatically. It uses the unexposed <strong>PyThreadState_SetAsyncExc</strong> function (via ctypes) to raise an exception in the context of the given thread. </p> <p>The following code allows (with some restrictions) to raise an Exception in a Python thread:</p> <p><strong>Example:</strong></p> <pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import threading import inspect import ctypes import time def _async_raise(tid, exctype): """raises the exception, performs cleanup if needed""" 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(tid, 0) raise SystemError("PyThreadState_SetAsyncExc failed") class Thread(threading.Thread): def _get_my_tid(self): """determines this (self's) thread id""" if not self.is_alive(): 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 raise AssertionError("could not determine the thread's id") def raise_exc(self, exctype): """raises the given exception type in the context of this thread""" _async_raise(self._get_my_tid(), exctype) def terminate(self): """raises SystemExit in the context of the given thread, which should cause the thread to exit silently (unless caught)""" self.raise_exc(SystemExit) def f(): try: while True: for i in range(10000): print(i) time.sleep(0.1) finally: print ("TERMINATING!!!") t = Thread(target = f) t.start() time.sleep(0.6) t.terminate() t.join()</pre> <p><strong>Output:</strong></p> <pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">0 1 2 3 4 5 TERMINATING!!!</pre> <h2>Conclusion</h2> <p>The key takeaways from this article were:</p> <ul> <li>What is Thread?</li> <li>Ways to kill a thread in Python: <ul> <li>Creating an Exit_Request flag.</li> <li>Using the <code>Multiprocessing </code>Module.</li> <li>Using the <code>trace </code>Module.</li> <li>Using <code>ctypes </code>to raise Exceptions in a thread</li> </ul> </li> </ul> <p>Please <strong><a href="https://blog.finxter.com/subscribe" target="_blank" rel="noreferrer noopener">subscribe </a></strong>and<strong> <a href="https://blog.finxter.com" target="_blank" rel="noreferrer noopener">stay tuned</a></strong><a href="https://blog.finxter.com" target="_blank" rel="noreferrer noopener"> </a>for more interesting articles!</p> <h2>References</h2> <ol> <li>https://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread</li> <li>http://net-informations.com/python/iq/kill.htm</li> <li>https://pybay.com/site_media/slides/raymond2017-keynote/threading.html</li> <li>http://tomerfiliba.com/recipes/Thread2/</li> </ol> <h2 class="wp-block-block">Where to Go From Here?</h2> <p>Enough theory, let’s get some practice!</p> <p>To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?</p> <p><strong>Practice projects is how you sharpen your saw in coding!</strong></p> <p>Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?</p> <p>Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.</p> <p>Join my free webinar <a rel="noreferrer noopener" href="https://blog.finxter.com/webinar-freelancer/" target="_blank">“How to Build Your High-Income Skill Python”</a> and watch how I grew my coding business online and how you can, too—from the comfort of your own home.</p> <p><a href="https://blog.finxter.com/webinar-freelancer/" target="_blank" rel="noreferrer noopener">Join the free webinar now!</a></p> <p>The post <a href="https://blog.finxter.com/how-to-kill-a-thread-in-python/" target="_blank" rel="noopener noreferrer">How To Kill A Thread In Python?</a> first appeared on <a href="https://blog.finxter.com/" target="_blank" rel="noopener noreferrer">Finxter</a>.</p> </div> https://www.sickgaming.net/blog/2020/10/23/how-to-kill-a-thread-in-python/ |