from IPython.html.widgets import interact
x = True
while True:
x = not x
get_ipython().kernel.do_one_iteration()
x
False
Interrupting the kernel kills only one active cell at a time.
from IPython.display import display, clear_output
import time
dy = 0.0
y = 0.0
while True:
y += dy * 0.1
clear_output()
display(y)
get_ipython().kernel.do_one_iteration()
time.sleep(0.1)
Now it's possible to run a second cell that has a widget doing tuning
@interact
def foo(arg=1):
global dy
dy = arg
It also works if you start the widget tuning cell first, and the loop cell second
Unfortunately, prints don't go to the right cells in this example
Here's an attempt at parallel execution that doesn't work
a, b = 0, 0
while True:
b = a % 10
get_ipython().kernel.do_one_iteration()
while True:
a += 1
get_ipython().kernel.do_one_iteration()
clear_output()
display(b)
time.sleep(0.05) # Not strictly necessary, but try to keep load down
0
--------------------------------------------------------------------------- KeyboardInterrupt Traceback (most recent call last) <ipython-input-37-017f248edb17> in <module>() 4 clear_output() 5 display(b) ----> 6 time.sleep(0.05) KeyboardInterrupt:
--------------------------------------------------------------------------- KeyboardInterrupt Traceback (most recent call last) <ipython-input-37-e791eab658ff> in <module>() 1 while True: 2 b = a % 10 ----> 3 get_ipython().kernel.do_one_iteration() /usr/local/lib/python2.7/dist-packages/IPython/kernel/zmq/ipkernel.pyc in do_one_iteration(self) 294 for stream in self.shell_streams: 295 # handle at most one request per iteration --> 296 stream.flush(zmq.POLLIN, 1) 297 stream.flush(zmq.POLLOUT) 298 /usr/local/lib/python2.7/dist-packages/zmq/eventloop/zmqstream.pyc in flush(self, flag, limit) 323 int : count of events handled (both send and recv) 324 """ --> 325 self._check_closed() 326 # unset self._flushed, so callbacks will execute, in case flush has 327 # already been called this iteration /usr/local/lib/python2.7/dist-packages/zmq/eventloop/zmqstream.pyc in _check_closed(self) 489 490 def _check_closed(self): --> 491 if not self.socket: 492 raise IOError("Stream is closed") 493 KeyboardInterrupt:
Note how the output is always zero. (It waits for the second cell to complete before returning to the first one)
Here's a version that does work (it uses coroutines and Python's yield
statement)
active = set()
def parallel(coroutine):
"""
Mark a function for parallel execution.
Works as a decorator, too
"""
active.add(coroutine())
return coroutine
def remove_all():
active.clear()
while True:
for act in active:
next(act)
get_ipython().kernel.do_one_iteration()
time.sleep(0.05)
a, b = 0, 0
def foo():
global a, b
while True:
b = a % 10
yield
parallel(foo)
ERROR! Session/line number was not unique in database. History logging moved to new session 3231
<function __main__.foo>
@parallel
def bar():
global a, b
while True:
a += 1
clear_output()
display(b)
yield
5
--------------------------------------------------------------------------- KeyboardInterrupt Traceback (most recent call last) <ipython-input-54-142308df753d> in <module>() 12 next(act) 13 get_ipython().kernel.do_one_iteration() ---> 14 time.sleep(0.05) KeyboardInterrupt:
Now the number printed is no longer always zero