Module tasks
source code
The tasks module provides a simple light-weight alternative to
threads.
When you have a long-running job you will want to run it in the
background, while the user does other things. There are four ways to do
this:
-
Use a new thread for each task.
-
Use callbacks from an idle handler.
-
Use a recursive mainloop.
-
Use this module.
Using threads causes a number of problems: they introduce race
conditions, often lead to many subtle bugs, and they require lots of
resources (you probably wouldn't want 10,000 threads running at once). In
particular, two threads can run at exactly the same time (perhaps on
different processors), so you have to be really careful that they don't
both try to update the same variables at the same time. This requires
lots of messy locking, which is hard to get right.
Callbacks work within a single thread. For example, you open a dialog
box and then tell the system to call one function if it's closed, and
another if the user clicks OK, etc. The function that opened the box then
returns, and the system calls one of the given callback functions later.
Callbacks only execute one at a time, so you don't have to worry about
race conditions. However, they are often very awkward to program with,
because you have to save state somewhere and then pass it to the
functions when they're called.
A recursive mainloop only works with nested tasks (you can create a
sub-task, but the main task can't continue until the sub-task has
finished), so they are not appropriate for long-running jobs.
Tasks use Python's generator API to provide a more pleasant interface
to callbacks. See the Task class (below) for more information.
|
Fail
|
|
Blocker
A Blocker object starts life with 'happened = False'.
|
|
IdleBlocker
An IdleBlocker blocks until a task starts waiting on it, then
immediately triggers.
|
|
TimeoutBlocker
Triggers after a set number of seconds.
|
|
InputBlocker
Triggers when os.read(stream) would not block.
|
|
OutputBlocker
Triggers when os.write(stream) would not block.
|
|
Task
Create a new Task when you have some long running function to run
in the background, but which needs to do work in 'chunks'.
|
|
check(blockers,
reporter=None)
See if any of the blockers have pending exceptions. |
source code
|
|
|
named_async(name)
Decorator that turns a generator function into a function that runs
the generator as a Task and returns the Task's finished blocker. |
source code
|
|
|
async(fn)
Decorator that turns a generator function into a function that runs
the generator as a Task and returns the Task's finished blocker. |
source code
|
|
|
|
|
tulip = Fail()
|
|
loop = tulip.get_event_loop()
|
See if any of the blockers have pending exceptions. If reporter is
None, raise the first and log the rest.
- Parameters:
reporter - invoke this function on each error
blockers ([Blocker])
|
Decorator that turns a generator function into a function that runs
the generator as a Task and returns the Task's finished blocker.
- Parameters:
name (str) - the name for the Task
|
Run a recursive mainloop until blocker is triggered.
- Parameters:
blocker (Blocker) - event to wait on
|