from IPython.lib import backgroundjobs as bg
import sys
import time
def sleepfunc(interval=2, *a, **kw):
args = dict(interval=interval,
args=a,
kwargs=kw)
time.sleep(interval)
return args
def diefunc(interval=2, *a, **kw):
time.sleep(interval)
raise Exception("Dead job with interval %s" % interval)
def printfunc(interval=1, reps=5):
for n in range(reps):
time.sleep(interval)
print('In the background... %i' % n)
sys.stdout.flush()
print('All done!')
sys.stdout.flush()
train_lenet.py
-
Fahad Khalid authoredFahad Khalid authored
Simple interactive bacgkround jobs with IPython
We start by loading the backgroundjobs
library and defining a few trivial functions to illustrate things with.
Now, we can create a job manager (called simply jobs
) and use it to submit new jobs.
Run the cell below, it will show when the jobs start. Wait a few seconds until you see the 'all done' completion message:
jobs = bg.BackgroundJobManager()
# Start a few jobs, the first one will have ID # 0
jobs.new(sleepfunc, 4)
jobs.new(sleepfunc, kw={'reps':2})
jobs.new('printfunc(1,3)')
Starting job # 0 in a separate thread.
Starting job # 2 in a separate thread.
Starting job # 3 in a separate thread.
<BackgroundJob #3: printfunc(1,3)>
In the background... 0
In the background... 1
In the background... 2
All done!
You can check the status of your jobs at any time:
jobs.status()
Completed jobs:
0 : <function sleepfunc at 0x10521f2f0>
2 : <function sleepfunc at 0x10521f2f0>
3 : printfunc(1,3)
For any completed job, you can get its result easily:
jobs[0].result
{'args': (), 'interval': 4, 'kwargs': {}}
Errors and tracebacks
The jobs manager tries to help you with debugging:
# This makes a couple of jobs which will die. Let's keep a reference to
# them for easier traceback reporting later
diejob1 = jobs.new(diefunc, 1)
diejob2 = jobs.new(diefunc, 2)
Starting job # 4 in a separate thread.
Starting job # 5 in a separate thread.
You can get the traceback of any dead job. Run the line below again interactively until it prints a traceback (check the status of the job):
print("Status of diejob1: %s" % diejob1.status)
diejob1.traceback() # jobs.traceback(4) would also work here, with the job number
Status of diejob1: Dead (Exception), call jobs.traceback() for details
[1;31m---------------------------------------------------------------------------[0m
[1;31mException[0m Traceback (most recent call last)
[1;32m/Users/minrk/dev/ip/mine/IPython/lib/backgroundjobs.py[0m in [0;36mcall[1;34m(self)[0m
[0;32m 489[0m [1;33m[0m[0m
[0;32m 490[0m [1;32mdef[0m [0mcall[0m[1;33m([0m[0mself[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[0m
[1;32m--> 491[1;33m [1;32mreturn[0m [0mself[0m[1;33m.[0m[0mfunc[0m[1;33m([0m[1;33m*[0m[0mself[0m[1;33m.[0m[0margs[0m[1;33m,[0m [1;33m**[0m[0mself[0m[1;33m.[0m[0mkwargs[0m[1;33m)[0m[1;33m[0m[0m
[0m
[1;32m<ipython-input-1-169e49434ce0>[0m in [0;36mdiefunc[1;34m(interval, *a, **kw)[0m
[0;32m 13[0m [1;32mdef[0m [0mdiefunc[0m[1;33m([0m[0minterval[0m[1;33m=[0m[1;36m2[0m[1;33m,[0m [1;33m*[0m[0ma[0m[1;33m,[0m [1;33m**[0m[0mkw[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[0m
[0;32m 14[0m [0mtime[0m[1;33m.[0m[0msleep[0m[1;33m([0m[0minterval[0m[1;33m)[0m[1;33m[0m[0m
[1;32m---> 15[1;33m [1;32mraise[0m [0mException[0m[1;33m([0m[1;34m"Dead job with interval %s"[0m [1;33m%[0m [0minterval[0m[1;33m)[0m[1;33m[0m[0m
[0m[0;32m 16[0m [1;33m[0m[0m
[0;32m 17[0m [1;32mdef[0m [0mprintfunc[0m[1;33m([0m[0minterval[0m[1;33m=[0m[1;36m1[0m[1;33m,[0m [0mreps[0m[1;33m=[0m[1;36m5[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[0m
[1;31mException[0m: Dead job with interval 1
This will print all tracebacks for all dead jobs:
jobs.traceback()
Traceback for: <BackgroundJob #4: <function diefunc at 0x10521f7b8>>
[1;31m---------------------------------------------------------------------------[0m
[1;31mException[0m Traceback (most recent call last)
[1;32m/Users/minrk/dev/ip/mine/IPython/lib/backgroundjobs.py[0m in [0;36mcall[1;34m(self)[0m
[0;32m 489[0m [1;33m[0m[0m
[0;32m 490[0m [1;32mdef[0m [0mcall[0m[1;33m([0m[0mself[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[0m
[1;32m--> 491[1;33m [1;32mreturn[0m [0mself[0m[1;33m.[0m[0mfunc[0m[1;33m([0m[1;33m*[0m[0mself[0m[1;33m.[0m[0margs[0m[1;33m,[0m [1;33m**[0m[0mself[0m[1;33m.[0m[0mkwargs[0m[1;33m)[0m[1;33m[0m[0m
[0m
[1;32m<ipython-input-1-169e49434ce0>[0m in [0;36mdiefunc[1;34m(interval, *a, **kw)[0m
[0;32m 13[0m [1;32mdef[0m [0mdiefunc[0m[1;33m([0m[0minterval[0m[1;33m=[0m[1;36m2[0m[1;33m,[0m [1;33m*[0m[0ma[0m[1;33m,[0m [1;33m**[0m[0mkw[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[0m
[0;32m 14[0m [0mtime[0m[1;33m.[0m[0msleep[0m[1;33m([0m[0minterval[0m[1;33m)[0m[1;33m[0m[0m
[1;32m---> 15[1;33m [1;32mraise[0m [0mException[0m[1;33m([0m[1;34m"Dead job with interval %s"[0m [1;33m%[0m [0minterval[0m[1;33m)[0m[1;33m[0m[0m
[0m[0;32m 16[0m [1;33m[0m[0m
[0;32m 17[0m [1;32mdef[0m [0mprintfunc[0m[1;33m([0m[0minterval[0m[1;33m=[0m[1;36m1[0m[1;33m,[0m [0mreps[0m[1;33m=[0m[1;36m5[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[0m
[1;31mException[0m: Dead job with interval 1
Traceback for: <BackgroundJob #5: <function diefunc at 0x10521f7b8>>
[1;31m---------------------------------------------------------------------------[0m
[1;31mException[0m Traceback (most recent call last)
[1;32m/Users/minrk/dev/ip/mine/IPython/lib/backgroundjobs.py[0m in [0;36mcall[1;34m(self)[0m
[0;32m 489[0m [1;33m[0m[0m
[0;32m 490[0m [1;32mdef[0m [0mcall[0m[1;33m([0m[0mself[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[0m
[1;32m--> 491[1;33m [1;32mreturn[0m [0mself[0m[1;33m.[0m[0mfunc[0m[1;33m([0m[1;33m*[0m[0mself[0m[1;33m.[0m[0margs[0m[1;33m,[0m [1;33m**[0m[0mself[0m[1;33m.[0m[0mkwargs[0m[1;33m)[0m[1;33m[0m[0m
[0m
[1;32m<ipython-input-1-169e49434ce0>[0m in [0;36mdiefunc[1;34m(interval, *a, **kw)[0m
[0;32m 13[0m [1;32mdef[0m [0mdiefunc[0m[1;33m([0m[0minterval[0m[1;33m=[0m[1;36m2[0m[1;33m,[0m [1;33m*[0m[0ma[0m[1;33m,[0m [1;33m**[0m[0mkw[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[0m
[0;32m 14[0m [0mtime[0m[1;33m.[0m[0msleep[0m[1;33m([0m[0minterval[0m[1;33m)[0m[1;33m[0m[0m
[1;32m---> 15[1;33m [1;32mraise[0m [0mException[0m[1;33m([0m[1;34m"Dead job with interval %s"[0m [1;33m%[0m [0minterval[0m[1;33m)[0m[1;33m[0m[0m
[0m[0;32m 16[0m [1;33m[0m[0m
[0;32m 17[0m [1;32mdef[0m [0mprintfunc[0m[1;33m([0m[0minterval[0m[1;33m=[0m[1;36m1[0m[1;33m,[0m [0mreps[0m[1;33m=[0m[1;36m5[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[0m
[1;31mException[0m: Dead job with interval 2
The job manager can be flushed of all completed jobs at any time:
jobs.flush()
Flushing 3 Completed jobs.
Flushing 2 Dead jobs.
After that, the status is simply empty:
jobs.status()
Jobs have a .join
method that lets you wait on their thread for completion:
j = jobs.new(sleepfunc, 2)
j.join?
Starting job # 0 in a separate thread.
Exercise
- Start a new job that calls
sleepfunc
with a 5-second wait - Print a short message that indicates you are waiting (note: you'll need to flush stdout to see that print output appear).
- Wait on the job and then print its result.