threading.Thread vs. signal.signal

Jp Calderone exarkun at
Sun Sep 18 01:47:58 CEST 2005

On Sat, 17 Sep 2005 19:24:54 -0400, Jack Orenstein <jao at> wrote:
>I'd like to create a program that invokes a function once a second,
>and terminates when the user types ctrl-c. So I created a signal
>handler, created a threading.Thread which does the invocation every
>second, and started the thread. The signal handler seems to be
>ineffective. Any idea what I'm doing wrong? This is on Fedora FC4 and
>Python 2.4.1. The code appears below.
>If I do the while ... sleep in the main thread, then the signal
>handler works as expected. (This isn't really a satisfactory
>implementation because the function called every second might
>take a significant fraction of a second to execute.)
>Jack Orenstein
>import sys
>import signal
>import threading
>import datetime
>import time
>class metronome(threading.Thread):
>     def __init__(self, interval, function):
>         threading.Thread.__init__(self)
>         self.interval = interval
>         self.function = function
>         self.done = False
>     def cancel(self):
>         print '>>> cancel'
>         self.done = True
>     def run(self):
>         while not self.done:
>             time.sleep(self.interval)
>             if self.done:
>                 print '>>> break!'
>                 break
>             else:
>                 self.function()
>def ctrl_c_handler(signal, frame):
>     print '>>> ctrl c'
>     global t
>     t.cancel()
>     sys.stdout.close()
>     sys.stderr.close()
>     sys.exit(0)
>signal.signal(signal.SIGINT, ctrl_c_handler)
>def hello():
>     print
>t = metronome(1, hello)

The problem is that you allowed the main thread to complete.  No longer running, it can no longer process signals.  If you add something like this to the end of the program, you should see the behavior you wanted:

    while not t.done:

Incidentally, the last 3 lines of ctrl_c_handler aren't really necessary.

That said, here's a simpler version of the same program, using Twisted:

    import datetime
    from twisted.internet import reactor, task

    def hello():

    task.LoopingCall(hello).start(1, now=False)

Hope this helps!


More information about the Python-list mailing list