Domanda

Io corro questo semplice codice:

import threading, time

class reqthread(threading.Thread):    
    def run(self):
        for i in range(0, 10):
            time.sleep(1)
            print('.')

try:
    thread = reqthread()
    thread.start()
except (KeyboardInterrupt, SystemExit):
    print('\n! Received keyboard interrupt, quitting threads.\n')

Ma quando l'eseguo, stampa

$ python prova.py
.
.
^C.
.
.
.
.
.
.
.
Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.6/threading.pyc'> ignored

In realtà discussione python ignorare la mia Ctrl + C Tastiera di interrupt e non stampa Received Keyboard Interrupt. Perché? Cosa c'è di sbagliato con questo codice?

È stato utile?

Soluzione

Prova

try:
  thread=reqthread()
  thread.daemon=True
  thread.start()
  while True: time.sleep(100)
except (KeyboardInterrupt, SystemExit):
  print '\n! Received keyboard interrupt, quitting threads.\n'

Senza la chiamata al time.sleep, il processo principale sta saltando fuori dal blocco try...except troppo presto, in modo che il KeyboardInterrupt non viene catturato. Il mio primo pensiero è stato quello di utilizzare thread.join, ma che sembra bloccare il processo principale (ignorando KeyboardInterrupt) fino a quando il thread è finito.

thread.daemon=True causa il thread di terminare quando finisce il processo principale.

Altri suggerimenti

Per riassumere le modifiche raccomandate nella il commenti , il seguente funziona bene per me:

try:
  thread = reqthread()
  thread.start()
  while thread.isAlive(): 
    thread.join(1)  # not sure if there is an appreciable cost to this.
except (KeyboardInterrupt, SystemExit):
  print '\n! Received keyboard interrupt, quitting threads.\n'
  sys.exit()

lieve modifica della soluzione di ubuntu.

La rimozione tread.daemon = true come suggerito da Eric e sostituendo il ciclo notte da signal.pause ():

import signal
try:
  thread=reqthread()
  thread.start()
  signal.pause() # instead of: while True: time.sleep(100)
except (KeyboardInterrupt, SystemExit):
  print '\n! Received keyboard interrupt, quitting threads.\n'

Il mio (hacky) soluzione è quella di scimmia-patch Thread.join() in questo modo:

def initThreadJoinHack():
  import threading, thread
  mainThread = threading.currentThread()
  assert isinstance(mainThread, threading._MainThread)
  mainThreadId = thread.get_ident()
  join_orig = threading.Thread.join
  def join_hacked(threadObj, timeout=None):
    """
    :type threadObj: threading.Thread
    :type timeout: float|None
    """
    if timeout is None and thread.get_ident() == mainThreadId:
      # This is a HACK for Thread.join() if we are in the main thread.
      # In that case, a Thread.join(timeout=None) would hang and even not respond to signals
      # because signals will get delivered to other threads and Python would forward
      # them for delayed handling to the main thread which hangs.
      # See CPython signalmodule.c.
      # Currently the best solution I can think of:
      while threadObj.isAlive():
        join_orig(threadObj, timeout=0.1)
    else:
      # In all other cases, we can use the original.
      join_orig(threadObj, timeout=timeout)
  threading.Thread.join = join_hacked

Mettere il try ... except in ogni thread e anche un signal.pause() in true main() funziona per me.

Attenzione per blocco importazione però. Sto indovinando questo è il motivo per cui Python non risolve ctrl-C per impostazione predefinita.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top