How do I exit a thread?


  • Pybytes Beta

    How do I kill thr() in this example? Does it have something to do with the id arg passed?

    def thr(id):
        from time import sleep
        i = 0
        while True:
            print(i)
            i += 1
            sleep(delay)
    
    import _thread
    _thread.start_new_thread(thr, (1, 0))
    

    Maybe should I do this?

    mythr = _thread.start_new_thread(thr, (1, 0))
    mythr.exit()

  • Global Moderator

    I think the concepts @larry-hems mentions apply to Micropython, but the function calls might differ.
    If I understand correctly, all threads in micropython are daemon threads, as they continue running after command is returned to the REPL. Only after a machine.reset() or pressing the reset button will the thread be closed automatically.


  • Pybytes Beta

    @larry-hems are you referring to regular Python or Pycom's implementation of MicroPython? Because I couldn't find a daemon flag, or multiprocessing as an option with Pycom's uPy.

    No daemon flag:
    https://docs.pycom.io/firmwareapi/micropython/_thread/

    No multiprocessing module:
    354d71b8-f869-4130-b7cb-e89cb954f7b5-image.png



  • @BetterAuto said in How do I exit a thread?:

    How do I kill thr() in this example?

    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.

    If you REALLY need to use a Thread, there is no way to kill thread directly. What you can do, however, is to use a "daemon thread". In fact, in Python, a Thread can be flagged as daemon:

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

    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)


  • Pybytes Beta

    This code based on @Eric24's suggestion does work. Ugly, but functional. I had trouble with my opening post code so I went back to the example in the docs and that works.

    import _thread
    import time
    
    kill = dict()
    
    def th_func(delay, id):
        global kill
        while True:
            if id in kill and kill[id]:
                break
            
            time.sleep(delay)
            print('Running thread %d' % id)
    
    for i in range(2):
        kill[i] = False
        _thread.start_new_thread(th_func, (i + 1, i))
    
    
    kill[0] = True
    kill[1] = True
    

    And this fails. _thread.exit() does not work from outside the thread.

    import _thread
    import time
    
    threads = dict()
    
    def th_func(delay, id):
        while True:
            time.sleep(delay)
            print('Running thread %d' % id)
    
    for i in range(2):
        threads[i] = _thread.start_new_thread(th_func, (i + 1, i))
    
    
    threads[0].exit()
    threads[1].exit()
    
    
    
    >>> Running thread 0
    Running thread 1
    Running thread 0
    Running thread 0
    Running thread 1
    Running thread 0
    threads[0].exit()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'exit'
    >>> threads[1].exit()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'exit'
    >>> Running thread 0
    Running thread 1
    Running thread 0
    
    >>>


  • +1, is it possible to kill the thread from outside ?


  • Pybytes Beta

    Thanks, I'll try it soon. (Don't have access to my WiPy at the moment.)



  • @BetterAuto Hmmm. The _thread.exit() function in the docs isn't exactly clear on how it should be used, but since it has no params, my best guess is that it would be executed from inside the thread you want to kill. You might also try just breaking out of the while True loop.

    Now, if the thread itself doesn't know it's supposed to die, you might have to implement an appropriate communications channel from the main program to the thread (could be as simple as a global "kill" variable), as there does not appear to be a _thread function that can kill a particular thread from outside that thread. It's a bit strange that this doesn't exist, as it's a common thing found in many threading implementations.


Log in to reply
 

Pycom on Twitter