manrajgrover / halo

💫 Beautiful spinners for terminal, IPython and Jupyter
MIT License
2.86k stars 148 forks source link

iPython notebook keyboard interrupt breaks cell when using Halo #35

Open manrajgrover opened 6 years ago

manrajgrover commented 6 years ago

Description

Currently, in an iPython notebook, if a user does not handle keyboard interrupt and the spinner is running, a KeyboardInterrupt is thrown but the spinner keeps spinning.

System settings

Error

Expected behaviour

In [5]: import time
   ...: import random
   ...:
   ...: spinner.start()
   ...: for i in range(100):
   ...:     spinner.text = '{0}% Downloaded dataset.zip'.format(i)
   ...:     time.sleep(random.random())
   ...: spinner.succeed('Downloaded dataset.zip')
   ...:
⠹ 4% Downloaded dataset.zip^C---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-5-81a625f23371> in <module>()
      5 for i in range(100):
      6     spinner.text = '{0}% Downloaded dataset.zip'.format(i)
----> 7     time.sleep(random.random())
      8 spinner.succeed('Downloaded dataset.zip')
      9

KeyboardInterrupt:

⠼ 4% Downloaded

Steps to recreate

Following snippet should recreate the error.

In [1]: from halo import Halo

In [2]: spinner = Halo(text='Downloading dataset.zip', spinner='dots')

In [3]: import time
   ...: import random
   ...:
   ...: spinner.start()
   ...: for i in range(100):
   ...:     spinner.text = '{0}% Downloaded dataset.zip'.format(i)
   ...:     time.sleep(random.random())
   ...: spinner.succeed('Downloaded dataset.zip')

People to notify

@ManrajGrover

winterjung commented 6 years ago

In this case, if you type spinner.stop() (doesn't saw but it is kept handling) and press Enter, the spinner stops. But I think you want a more elegant solution.

To solve this problem, we capture KeyboardInterrupt signal, pass to the thread and stop a task immediately. One of the solutions is to implement specific thread class inherited thread.Thread like this. Second is to using signal module. In this way code is more clear and much better but there are maybe platform-specific issues.

I used the second way to solve the problem. Please review my method.

ipython-gif

winterjung commented 6 years ago

@ManrajGrover Can I send a PR for review?

manrajgrover commented 6 years ago

@JungWinter I would need a little more time to review the methods. Apologies for the delay.

manrajgrover commented 6 years ago

With reference to #38, adding test case seems to fail on Appveyor. Need to find the reason behind this.