简体   繁体   中英

Control-C not stopping thread/spinning cursor

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

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

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
        ...

It is not really an answer, because I cannot explain what really happens, but I could partially reproduce. It looks like copy_file swallows the KeyboardInterrupt and raises another exception. If that happens, as the processing_flag.set() is only in the normal and except KeyboardInterrupt 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...)

Workarounds.

I could find 2 possible workarounds

  • use except without any filtering:

     try: shutil.copyfile(sfile, dfile) processing_flag.set() except: processing_flag.set() pass 

    that should be enough to catch any possible exception raised by copyfile

  • use a finally block. I personally prefere that way, because it is really what finally is aimed to: execute that branch whatever could happen. In that case, you could even remove the except block and have just a try:... finally:... :

     try: shutil.copyfile(sfile, dfile) finally: processing_flag.set() 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM