Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
589 views
in Technique[技术] by (71.8m points)

multithreading - Terminate a multi-thread python program

How to make a multi-thread python program response to Ctrl+C key event?

Edit: The code is like this:

import threading
current = 0

class MyThread(threading.Thread):
    def __init__(self, total):
        threading.Thread.__init__(self)
        self.total = total

    def stop(self):
        self._Thread__stop()

    def run(self):
        global current
        while current<self.total:
            lock = threading.Lock()
            lock.acquire()
            current+=1
            lock.release()
            print current

if __name__=='__main__':

    threads = []
    thread_count = 10
    total = 10000
    for i in range(0, thread_count):
        t = MyThread(total)
        t.setDaemon(True)
        threads.append(t)
    for i in range(0, thread_count):
        threads[i].start()

I tried to remove join() on all threads but it still doesn't work. Is it because the lock segment inside each thread's run() procedure?

Edit: The above code is supposed to work but it always interrupted when current variable was in 5,000-6,000 range and through out the errors as below

Exception in thread Thread-4 (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner
  File "test.py", line 20, in run
<type 'exceptions.TypeError'>: unsupported operand type(s) for +=: 'NoneType' and 'int'
Exception in thread Thread-2 (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner
  File "test.py", line 22, in run
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Make every thread except the main one a daemon (t.daemon = True in 2.6 or better, t.setDaemon(True) in 2.6 or less, for every thread object t before you start it). That way, when the main thread receives the KeyboardInterrupt, if it doesn't catch it or catches it but decided to terminate anyway, the whole process will terminate. See the docs.

edit: having just seen the OP's code (not originally posted) and the claim that "it doesn't work", it appears I have to add...:

Of course, if you want your main thread to stay responsive (e.g. to control-C), don't mire it into blocking calls, such as joining another thread -- especially not totally useless blocking calls, such as joining daemon threads. For example, just change the final loop in the main thread from the current (utterless and damaging):

for i in range(0, thread_count):
    threads[i].join()

to something more sensible like:

while threading.active_count() > 0:
    time.sleep(0.1)

if your main has nothing better to do than either for all threads to terminate on their own, or for a control-C (or other signal) to be received.

Of course, there are many other usable patterns if you'd rather have your threads not terminate abruptly (as daemonic threads may) -- unless they, too, are mired forever in unconditionally-blocking calls, deadlocks, and the like;-).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...