다중 스레드 Python 프로그램 종료
Ctrl + C 키 이벤트에 다중 스레드 Python 프로그램 응답을 만드는 방법은 무엇입니까?
편집 : 코드는 다음과 같습니다.
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()
모든 스레드에서 join ()을 제거하려고했지만 여전히 작동하지 않습니다. 각 스레드의 run () 프로 시저 내부의 잠금 세그먼트 때문입니까?
편집 : 위의 코드는 작동해야하지만 현재 변수가 5,000-6,000 범위에있을 때 항상 중단되고 아래와 같은 오류가 발생합니다.
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
기본 스레드를 제외한 모든 스레드를 데몬으로 만듭니다 ( t.daemon = True
2.6 이상 t.setDaemon(True)
에서는 2.6 이하에서는 t
시작하기 전에 모든 스레드 개체 에 대해). 이렇게하면 메인 스레드가 KeyboardInterrupt를 수신 할 때이를 포착하지 못하거나 포착하지만 어쨌든 종료하기로 결정하면 전체 프로세스가 종료됩니다. 문서를 참조하십시오 .
편집 : 방금 OP의 코드 (원래 게시되지 않음)와 "작동하지 않는다"라는 주장을 보았을 때 추가해야하는 것 같습니다 ... :
물론 메인 스레드가 응답 성을 유지하기를 원한다면 (예 : control-C), join
다른 스레드 를 사용 하는 것과 같이 호출을 차단하지 마십시오. 특히 데몬 스레드 를 사용 하는 것과 같이 완전히 쓸모없는 호출을 차단 하지 마십시오 . 예를 들어, 메인 스레드의 최종 루프를 현재에서 변경하십시오 (완전하고 손상됨).join
for i in range(0, thread_count):
threads[i].join()
다음과 같이 더 현명한 것으로 바꾸십시오.
while threading.active_count() > 0:
time.sleep(0.1)
메인이 모든 스레드가 자체적으로 종료하거나 control-C (또는 기타 신호)를 수신하는 것보다 더 나은 것이없는 경우.
물론, 당신의 쓰레드가 갑자기 종료되는 것을 원하지 않는다면 (데몬 쓰레드가 그러 하듯이) 사용 가능한 패턴이 많이 있습니다 .- 그들 역시 무조건적으로 차단하는 호출, 교착 상태 등에서 영원히 빠져 나가지 않는 한 ;-) .
두 가지 주요 방법이 있습니다. 하나는 깔끔하고 하나는 쉬운 방법입니다.
깨끗한 방법은 메인 스레드에서 KeyboardInterrupt를 포착하고 백그라운드 스레드가 종료 할 수 있도록 확인할 수있는 플래그를 설정하는 것입니다. 전역을 사용하는 단순 / 약간 지저분한 버전은 다음과 같습니다.
exitapp = False
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
exitapp = True
raise
def threadCode(...):
while not exitapp:
# do work here, watch for exitapp to be True
지저분하지만 쉬운 방법은 KeyboardInterrupt를 잡아서 모든 스레드를 즉시 종료하는 os._exit ()를 호출하는 것입니다.
노동자는 당신을 위해 도움이 될 수 있습니다
#!/usr/bin/env python
import sys, time
from threading import *
from collections import deque
class Worker(object):
def __init__(self, concurrent=1):
self.concurrent = concurrent
self.queue = deque([])
self.threads = []
self.keep_interrupt = False
def _retain_threads(self):
while len(self.threads) < self.concurrent:
t = Thread(target=self._run, args=[self])
t.setDaemon(True)
t.start()
self.threads.append(t)
def _run(self, *args):
while self.queue and not self.keep_interrupt:
func, args, kargs = self.queue.popleft()
func(*args, **kargs)
def add_task(self, func, *args, **kargs):
self.queue.append((func, args, kargs))
def start(self, block=False):
self._retain_threads()
if block:
try:
while self.threads:
self.threads = [t.join(1) or t for t in self.threads if t.isAlive()]
if self.queue:
self._retain_threads()
except KeyboardInterrupt:
self.keep_interrupt = True
print "alive threads: %d; outstanding tasks: %d" % (len(self.threads), len(self.queue))
print "terminating..."
# example
print "starting..."
worker = Worker(concurrent=50)
def do_work():
print "item %d done." % len(items)
time.sleep(3)
def main():
for i in xrange(1000):
worker.add_task(do_work)
worker.start(True)
main()
print "done."
# to keep shell alive
sys.stdin.readlines()
차라리이 블로그 게시물 에서 제안한 코드를 사용 하겠습니다 .
def main(args):
threads = []
for i in range(10):
t = Worker()
threads.append(t)
t.start()
while len(threads) > 0:
try:
# Join all threads using a timeout so it doesn't block
# Filter out threads which have been joined or are None
threads = [t.join(1000) for t in threads if t is not None and t.isAlive()]
except KeyboardInterrupt:
print "Ctrl-c received! Sending kill to threads..."
for t in threads:
t.kill_received = True
What I have changed is the t.join from t.join(1) to t.join(1000). The actual number of seconds does not matter, unless you specify a timeout number, the main thread will stay responsive to Ctrl+C. The except on KeyboardInterrupt makes the signal handling more explicit.
You can always set your threads to "daemon" threads like:
t.daemon = True
t.start()
And whenever the main thread dies all threads will die with it.
http://www.regexprn.com/2010/05/killing-multithreaded-python-programs.html
If you spawn a Thread like so - myThread = Thread(target = function)
- and then do myThread.start(); myThread.join()
. When CTRL-C is initiated, the main thread doesn't exit because it is waiting on that blocking myThread.join()
call. To fix this, simply put in a timeout on the .join() call. The timeout can be as long as you wish. If you want it to wait indefinitely, just put in a really long timeout, like 99999. It's also good practice to do myThread.daemon = True
so all the threads exit when the main thread(non-daemon) exits.
thread1 = threading.Thread(target=your_procedure, args = (arg_1, arg_2))
try:
thread1.setDaemon(True) # very important
thread1.start()
except (KeyboardInterrupt, SystemExit):
cleanup_stop_thread();
sys.exit()
When you want to kill the thread just use:
thread1.join(0)
참고URL : https://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program
'IT TIP' 카테고리의 다른 글
Visual Studio에서 여러 줄 찾기 및 바꾸기 (0) | 2020.10.29 |
---|---|
C에서 배열을 반환 할 수 없다는 것은 실제로 무엇을 의미합니까? (0) | 2020.10.29 |
Android : '강제 종료'후 애플리케이션을 자동으로 다시 시작하는 방법은 무엇입니까? (0) | 2020.10.29 |
Javadoc : HTML 태그없이 줄 바꿈? (0) | 2020.10.29 |
Google Maps API V3 : A 지점에서 B 지점 (파란색 선)까지의 방향을 어떻게 표시하나요? (0) | 2020.10.29 |