una terminar salir que programa opcion juego hacer funcion finalizar consola como codigo python multithreading

salir - terminar un if en python



Terminar un programa python de hilos mĂșltiples (7)

¿Cómo hacer una respuesta de programa python multihilo al evento de tecla Ctrl + C?

Editar: el código es así:

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

Traté de eliminar join () en todos los hilos, pero todavía no funciona. ¿Es porque el segmento de bloqueo dentro del procedimiento run () de cada hilo?

Editar: Se supone que el código anterior funciona, pero siempre se interrumpió cuando la variable actual estaba en un rango de 5,000-6,000 y en todos los errores como se muestra a continuación.

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


Haga que todos los hilos, excepto el principal, sean daemon ( t.daemon = True en 2.6 o mejor, t.setDaemon(True) en 2.6 o menos, para cada objeto de hilo t antes de iniciarlo). De esta forma, cuando el hilo principal recibe KeyboardInterrupt, si no lo detecta o lo atrapa pero decide terminar de todos modos, todo el proceso terminará. Ver los documentos .

editar : acaba de ver el código del OP (no publicado originalmente) y la afirmación de que "no funciona", parece que tengo que agregar ...:

Por supuesto, si quieres que tu hilo principal se mantenga receptivo (p. Ej., Para controlar C), no lo atasques en llamadas de bloqueo, como join otro hilo, especialmente las llamadas de bloqueo no totalmente inútiles , como la join de hilos daemon. . Por ejemplo, simplemente cambie el bucle final en el hilo principal del actual (sin sentido y perjudicial):

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

a algo más sensible como:

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

si su main no tiene nada mejor que hacer que el que todos los hilos terminen solos, o que se reciba un C de control (u otra señal).

Por supuesto, hay muchos otros patrones utilizables si prefiere que sus hilos no terminen abruptamente (como pueden hacerlo los hilos daemonicos), a menos que ellos también estén atrapados para siempre en bloqueos incondicionales, bloqueos, y cosas por el estilo ;-) .


Hay dos formas principales, una limpia y otra fácil.

La manera más limpia es capturar KeyboardInterrupt en su hilo principal y establecer un indicador que los hilos de su fondo puedan verificar para que sepan salir; aquí hay una versión simple / ligeramente desordenada usando un global:

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

La manera desordenada pero fácil es atrapar KeyboardInterrupt y llamar a os._exit (), que termina todos los hilos inmediatamente.


Prefiero ir con el código propuesto en esta publicación de blog :

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

Lo que he cambiado es la t.unión de t.join (1) a t.join (1000) . El número real de segundos no importa, a menos que especifique un número de tiempo de espera, el hilo principal seguirá siendo sensible a Ctrl + C. El excepto en KeyboardInterrupt hace que el manejo de la señal sea más explícito.


Si engendras un hilo como so - myThread = Thread(target = function) - y luego haces myThread.start(); myThread.join() myThread.start(); myThread.join() . Cuando se inicia CTRL-C, el hilo principal no se myThread.join() porque está esperando que bloquee la llamada myThread.join() . Para solucionar esto, simplemente ponga un tiempo de espera en la llamada .join (). El tiempo de espera puede ser el tiempo que desee. Si desea que espere indefinidamente, simplemente espere mucho tiempo, como 99999. También es una buena práctica hacer myThread.daemon = True para que todos los subprocesos myThread.daemon = True cuando el hilo principal (no demonio) finalice.



Un trabajador puede ser útil para usted:

#!/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()


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

Cuando quieras matar el hilo solo usa:

thread1.join(0)