3

I am close to finishing my program, and I wanted to fix this error before making my first ever release.

This is the error I'm talking about:

Exception ignored in: <module 'threading' from '/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py'>
Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1281, in _shutdown
    t.join()
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1032, in join
    self._wait_for_tstate_lock()
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1048, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt

I start the threads like this:

def init(self):

    new_post_stream_thread = threading.Thread(target=self.new_post_stream)
    process_posts = threading.Thread(target=self.process_posts)
    print('\nStarting threads...')
    print('- - - - - - - - - -\n')
    new_post_stream_thread.start()
    process_posts.start()

And that's basically it. How would I catch this exception? I tried with a try except already but it doesn't catch anything.

Here's the MCVE:

import threading
import time

class MCVE:

    def __init__(self):

        self.list_1 = []

        self.init()

    def thread_1(self):

        while True:
            self.list_1.append('whatever')
            time.sleep(5)

    def thread_2(self):

        while True:
            for id, entry in enumerate(self.list_1):
                print('ID {} | entry: {}'.format(id, entry))
            time.sleep(10)

    def init(self):
        thread_1 = threading.Thread(target=self.thread_1)
        thread_2 = threading.Thread(target=self.thread_2)
        print('\nStarting threads...')
        print('- - - - - - - - - -\n')
        thread_1.start()
        thread_2.start()


def main():

    example = MCVE()

if __name__ == "__main__":
    main()
G. Ramistella
  • 1,327
  • 1
  • 9
  • 19
  • What's `new_post_stream` and `process_posts`? And did you mean to use a method called `init` instead of the magic constructor `__init__`? – JacobIRR Jun 28 '19 at 17:49
  • The first thread streams posts from source, the second processes them as soon as they are available. Yes, `init` is called from `__init__`, I wanted to make the code just a bit cleaner. – G. Ramistella Jun 28 '19 at 17:54
  • actually this may help: https://stackoverflow.com/questions/3788208/threading-ignores-keyboardinterrupt-exception – JacobIRR Jun 28 '19 at 18:22

2 Answers2

0

You didn't provide a reproducible example, but this successfully stops the program without raising an uncaught exception:

def foo(n):
    import time
    try:
        for i in range(n):
            time.sleep(i)
    except KeyboardInterrupt:
        print("Clean exit....")
        return
JacobIRR
  • 8,545
  • 8
  • 39
  • 68
  • its just a function. You can call `foo(5)` and while its running, hit Control+C and you will see the printed message – JacobIRR Jun 28 '19 at 17:58
  • Alright. This is not working for me. I am not sure where I should use this `except`, to successfully catch this error. – G. Ramistella Jun 28 '19 at 18:03
  • You can start by wrapping every possible call at every level with `try/except` to see if it works. If it does, just remove the calls until you find the one that was working. If it doesn't work, it may require some special threading magic in your case. – JacobIRR Jun 28 '19 at 18:04
  • Could you explain this threading magic? The program is quite large and wrapping every single call in try/except is a bit tedious. – G. Ramistella Jun 28 '19 at 18:09
  • not without seeing a MCVE: https://stackoverflow.com/help/minimal-reproducible-example – JacobIRR Jun 28 '19 at 18:10
  • Added the MCVE. – G. Ramistella Jun 28 '19 at 18:22
  • 1
    Found the fix. `thread.daemon = True` + `except KeyboardInterrupt` in `main()` does the trick. – G. Ramistella Jun 28 '19 at 18:35
0

This might be a little late, Try "Event()" method in threading module and then use signal module and its methods to catch signals. I will leave a link below, Miguel Grinberg posted an easy and clear explanation about this.

link : https://blog.miguelgrinberg.com/post/how-to-kill-a-python-thread

ramixix
  • 33
  • 5
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](https://stackoverflow.com/review/late-answers/28329419) – Adam Marshall Feb 15 '21 at 16:45