Repository navigation
Asynchrony
This library features a powerful Context Manager-based asynchronous execution system. All hardware-bound actions, such as Mouse, Keyboard, Screen, Sound, or System operations, can be seamlessly queued and executed in the background. This architecture allows you to perform heavy operations concurrently without blocking your main script's logic.
Most core controllers (Mouse, Keyboard, Screen, Sound, System) inherit from a queueable controller base. This means any action they provide can be executed either synchronously (blocking the main thread) or asynchronously (queued in a background worker thread).
To execute actions asynchronously, simply wrap them inside a with controller.asynchronous() as controller_task: block. All actions invoked on that controller within the block will be queued and executed sequentially in the background.
Tip
All actions return Self, meaning they can be fluidly chained together. For instance, Mouse().move(x = 250, y = 500).click() queues both actions sequentially within the same background task.
Example:
mouse = Mouse()
with mouse.asynchronous() as mouse_task:
mouse.move(x = 250, y = 500)
mouse.scroll(amount = 1000, direction = "down")Because every controller is queueable, they all inherit basic timing capabilities. These allow you to inject precise pauses directly into your asynchronous chains.
Description:
Pauses execution for an exact amount of seconds. Can be chained and queued asynchronously.
Arguments:
-
duration(float): Seconds. Must be ≥ 0.
Returns:
Self
Example:
with mouse.asynchronous() as mouse_task: mouse.wait(duration = 2.5)Description:
Pauses execution for a random duration between two limits. Can be chained and queued asynchronously.
Arguments:
-
minimum_duration(float): Seconds. Must be ≥ 0. -
maximum_duration(float): Seconds. Must be ≥ 0.
Returns:
Self
Example:
with mouse.asynchronous() as mouse_task:
mouse.wait_random(minimum_duration = 1, maximum_duration = 3)Description:
Pauses execution until a given function or lambda condition evaluates to True. Can be chained and queued asynchronously.
Arguments:
condition_function(Callable[[], bool])-
timeout(float): Seconds. Must be ≥ 0. -
poll_interval(float): Seconds. Must be > 0.
Returns:
Self
Example:
with mouse.asynchronous() as mouse_task:
mouse.wait_until(
condition_function = lambda: KeyboardInfo().is_pressed(key = "shift"),
timeout = 5,
poll_interval = 0.1
)When you use the asynchronous() context manager, it returns a Task object. This object allows you to monitor and control the background thread.
Description:
Blocks the calling thread until the task is complete or cancelled.
Returns:
None
Example:
with mouse.asynchronous() as mouse_task: mouse.move(x = 500, y = 500)
mouse_task.wait()Description:
Cancels the task if it hasn't started or is currently running.
Returns:
None
Example:
with mouse.asynchronous() as mouse_task: mouse.move(x = 250, y = 500)
image_found = screen.locate_image(
image_path = "error.png",
confidence = 0.9,
region = [250, 250, 500, 500],
monitor_index = 0
)
if image_found: mouse_task.cancel()Description:
Checks if the task is complete or cancelled.
Returns:
bool
Example:
with keyboard.asynchronous() as keyboard_task: keyboard.write("Hello, world!")
with mouse.asynchronous() as mouse_task:
mouse.wander_until(condition_function = lambda: keyboard_task.is_done)To fetch the return value(s) of your asynchronous actions, you can use the last_result or results properties directly on the returned Task object once it finishes executing.
Tip
Both last_result and results are also available on the controller object itself. This is extremely useful for fetching results at the end of a synchronous chain.
Description:
Stores the return value of the very last action executed in the task.
Example:
with screen.asynchronous() as screen_task:
screen.locate_image(
image_path = "button.png",
confidence = 0.9,
limit = 1,
region = (250, 250, 500, 500),
monitor_index = 0
)
screen.locate_text(
text = "Submit",
region = (250, 250, 500, 500),
exact_match = True,
monitor_index = 0
)
result = screen_task.last_resultDescription:
A list containing the return values of all actions executed in the task, in the order they were queued.
Example:
with screen.asynchronous() as screen_task:
screen.locate_image(
image_path = "button.png",
confidence = 0.9,
limit = 1,
region = (250, 250, 500, 500),
monitor_index = 0
)
screen.locate_text(
text = "Submit",
region = (250, 250, 500, 500),
exact_match = True,
monitor_index = 0
)
results = screen_task.results