Control-C not stopping thread/spinning cursor
<p>I have code that copies files. When it is doing so a cursor spins. This all works fine. However if I use <kbd>Ctrl</kbd>+<kbd>C</kbd> to stop the copy I expect the <code>KeyboardInterrupt</code> to set the event and the cursor to stop spinning. The copy stops however the cursor spins forever, why is this?</p>

<p>I tried putting a print into the Interrupt and that did not get displayed, so it seems it is not being called?</p>

<pre><code>def spinning_cursor(event):
      for j in itertools.cycle('/-\|'):
          if not event.is_set():
              sys.stdout.write(j)
              sys.stdout.flush()
              time.sleep(0.1)
              sys.stdout.write('\b')
          else:
              return


def copy_file(sfile, dfile, sync):
    processing_flag = Event()
    Thread(target = spinning_cursor, kwargs = {'event': processing_flag}).start()
    if os.path.exists(sfile):
        try:
            shutil.copyfile(sfile, dfile)
            processing_flag.set()
        except KeyboardInterrupt:
            processing_flag.set()
            pass
        ...
</code></pre>

<p>It is not really an answer, because I cannot explain what really happens, but I could partially reproduce. It looks like <code>copy_file</code> <em>swallows</em> the KeyboardInterrupt and raises another exception. If that happens, as the <code>processing_flag.set()</code> is only in the normal and <code>except KeyboardInterrupt</code> branches, control never passes there. As a consequence, the Event is never set and the child thread keeps on spinning (that's what I did to reproduce the behaviour...)</p>

<h3>Workarounds.</h3>

<p>I could find 2 possible workarounds</p>

<ul>
<li><p>use <code>except</code> without any filtering:</p>

<pre><code>try:
    shutil.copyfile(sfile, dfile)
    processing_flag.set()
except:
    processing_flag.set()
    pass
</code></pre>

<p>that should be enough to catch any possible exception raised by <code>copyfile</code></p></li>
<li><p>use a <code>finally</code> block. I personally prefere that way, because it is really what <code>finally</code> is aimed to: execute that branch whatever could happen. In that case, you could even remove the <code>except</code> block and have just a <code>try:... finally:...</code>:</p>

<pre><code>try:
    shutil.copyfile(sfile, dfile)
finally:
    processing_flag.set()
</code></pre></li>
</ul>

python multithreading