Module:lib.backgroundjobs
Manage background (threaded) jobs conveniently from an interactive shell.
This module provides a BackgroundJobManager class. This is the main classmeant for public usage, it implements an object which can create and managenew background jobs.
It also provides the actual job classes managed by these BackgroundJobManagerobjects, see their docstrings below.
This system was inspired by discussions with B. Granger and theBackgroundCommand class described in the book Python Scripting forComputational Science, by H. P. Langtangen:
http://folk.uio.no/hpl/scripting
(although ultimately no code from this text was used, as IPython’s system is aseparate implementation).
An example notebook is provided in our documentation illustrating interactiveuse of the system.
4 Classes
- classIPython.lib.backgroundjobs.BackgroundJobManager
Bases:
objectClass to manage a pool of backgrounded threaded jobs.
Below, we assume that ‘jobs’ is a BackgroundJobManager instance.
Usage summary (see the method docstrings for details):
jobs.new(…) -> start a new job
jobs() or jobs.status() -> print status summary of all jobs
jobs[N] -> returns job number N.
foo = jobs[N].result -> assign to variable foo the result of job N
jobs[N].traceback() -> print the traceback of dead job N
jobs.remove(N) -> remove (finished) job N
jobs.flush() -> remove all finished jobs
As a convenience feature, BackgroundJobManager instances provide theutility result and traceback methods which retrieve the correspondinginformation from the jobs list:
jobs.result(N) <–> jobs[N].resultjobs.traceback(N) <–> jobs[N].traceback()
While this appears minor, it allows you to use tab completioninteractively on the job manager instance.
- __init__()
- flush()
Flush all finished jobs (completed and dead) from lists.
Running jobs are never flushed.
It first calls _status_new(), to update info. If any jobs havecompleted since the last _status_new() call, the flush operationaborts.
- new(func_or_exp,*args,**kwargs)
Add a new background job and start it in a separate thread.
There are two types of jobs which can be created:
1. Jobs based on expressions which can be passed to an eval() call.The expression must be given as a string. For example:
job_manager.new(‘myfunc(x,y,z=1)’[,glob[,loc]])
The given expression is passed to eval(), along with the optionalglobal/local dicts provided. If no dicts are given, they areextracted automatically from the caller’s frame.
A Python statement is NOT a valid eval() expression. Basically, youcan only use as an eval() argument something which can go on the rightof an ‘=’ sign and be assigned to a variable.
For example,”print ‘hello’” is not valid, but ‘2+3’ is.
2. Jobs given a function object, optionally passing additionalpositional arguments:
job_manager.new(myfunc, x, y)
The function is called with the given arguments.
If you need to pass keyword arguments to your function, you mustsupply them as a dict named kw:
job_manager.new(myfunc, x, y, kw=dict(z=1))
The reason for this asymmetry is that the new() method needs tomaintain access to its own keywords, and this prevents name collisionsbetween arguments to new() and arguments to your own functions.
In both cases, the result is stored in the job.result field of thebackground job object.
You can set
daemonattribute of the thread by giving the keywordargumentdaemon.Notes and caveats:
1. All threads running share the same standard output. Thus, if yourbackground jobs generate output, it will come out on top of whateveryou are currently writing. For this reason, background jobs are bestused with silent functions which simply return their output.
2. Threads also all work within the same global namespace, and thissystem does not lock interactive variables. So if you send job to thebackground which operates on a mutable object for a long time, andstart modifying that same mutable object interactively (or in anotherbackgrounded job), all sorts of bizarre behaviour will occur.
3. If a background job is spending a lot of time inside a C extensionmodule which does not release the Python Global Interpreter Lock(GIL), this will block the IPython prompt. This is simply because thePython interpreter can only switch between threads at Pythonbytecodes. While the execution is inside C code, the interpreter mustsimply wait unless the extension module releases the GIL.
4. There is no way, due to limitations in the Python threads library,to kill a thread once it has started.
- remove(num)
Remove a finished (completed or dead) job.
- result(N)→returntheresultofjobN.
- status(verbose=0)
Print a status of all jobs currently being managed.
- classIPython.lib.backgroundjobs.BackgroundJobBase
Bases:
ThreadBase class to build BackgroundJob classes.
The derived classes must implement:
Their own __init__, since the one here raises NotImplementedError. Thederived constructor must call self._init() at the end, to provide commoninitialization.
A strform attribute used in calls to __str__.
A call() method, which will make the actual execution call and mustreturn a value to be held in the ‘result’ field of the job object.
- __init__()
Must be implemented in subclasses.
Subclasses must call
_init()for standard initialisation.
- run()
Method representing the thread’s activity.
You may override this method in a subclass. The standard run() methodinvokes the callable object passed to the object’s constructor as thetarget argument, if any, with sequential and keyword arguments takenfrom the args and kwargs arguments, respectively.
- classIPython.lib.backgroundjobs.BackgroundJobExpr(expression,glob=None,loc=None)
Bases:
BackgroundJobBaseEvaluate an expression as a background job (uses a separate thread).
- __init__(expression,glob=None,loc=None)
Create a new job from a string which can be fed to eval().
global/locals dicts can be provided, which will be passed to the evalcall.
- classIPython.lib.backgroundjobs.BackgroundJobFunc(func,*args,**kwargs)
Bases:
BackgroundJobBaseRun a function call as a background job (uses a separate thread).
- __init__(func,*args,**kwargs)
Create a new job from a callable object.
Any positional arguments and keyword args given to this constructorafter the initial callable are passed directly to it.