Skip to content

The pattern

Cancellation Token is a pattern that allows us to cancel calculations that we no longer need. It is implemented out of the box in many programming languages, for example in C# and in Go. However, there was still no sane implementation in Python, until the cantok library appeared.

The essence of the pattern is that we pass special objects to functions and constructors, through which the executing code can determine whether it should continue its execution. When deciding whether to allow code execution to continue, this object can both take into account the restrictions imposed on it, such as the maximum code execution time, and receive signals about the need to stop from the outside, for example from another thread or a coroutine. Thus, we do not nail down the logic associated with stopping code execution, for example, by directly tracking loop counters, but implement Dependency Injection of this restriction.

In addition, the pattern assumes that various restrictions can be combined with each other without limit: if at least one of the restrictions is not met, code execution will be interrupted. It is assumed that each function in the call stack will call other functions, passing its token directly to them, or wrapping it in another token with stricter restrictions.

Unlike other ways of stopping code execution, tokens do not force the execution thread to be interrupted. The interruption occurs "gently", allowing the code to terminate correctly, release all held resources and restore consistency.

It is highly desirable for library developers to use this pattern for any long-running operations. Your function can accept a token as an optional argument, with a default value that imposes minimal restrictions or none at all. If the user wishes, they can pass their token to it, imposing stricter restrictions on the library code. In addition to a more convenient and extensible API, this will give the library an advantage in the form of better testability, because the restrictions are no longer hardcoded into the function, which means they can be set to any value needed for testing. In addition, the library developer no longer needs to think about all the numerous restrictions that can be imposed on their code — the user can take care of it themselves if they need to.