Unblock¶
A common problem developers encounter when working with an asyncio event loop is long blocking code.
This can be caused by a number of things, but the most common is a call to a library that is not async-aware, and has
many blocking operations (such as requests
, or even the built-in open()
+ read()
functions).
To alleviate this, NioBot provides an "unblock" utility, which is a simple async function that will run any blocking
code in the event loop executor, and returns the result, without pausing the event loop.
This is equivalent to loop.run_in_executor(None, func, *args, **kwargs)
.
A good example
This will read the contents of a file, without blocking the event loop, unlike the following code:A bad example
from niobot import NioBot, command
from niobot.utils import run_blocking
bot = NioBot(...)
@bot.command(name="read")
async def read_file(ctx: Context, filename: str):
with open(filename, "r") as f:
contents = f.read()
await ctx.respond(contents)
bot.run(...)
f.read()
finishes,
which is really bad if the file is large, or the disk is slow. For example, if you read at 1mb/s, and you have
a 10 megabyte file, you will block the event loop for approximately 10 seconds, which means your program
cannot do anything in those ten seconds, and as such your bot will appear to be non-functional!
run_blocking
async
¶
Takes a blocking function and runs it in a thread, returning the result.
You should use this for any long-running functions that may take a long time to respond that are not coroutines that you can await. For example, running a subprocess.
Example
Parameters:
Name | Type | Description | Default |
---|---|---|---|
function
|
Callable[..., T]
|
The function to call. Make sure you do not call it, just pass it. |
required |
args
|
Any
|
The arguments to pass to the function. |
()
|
kwargs
|
Any
|
The keyword arguments to pass to the function. |
{}
|
Returns:
Type | Description |
---|---|
T
|
The result of the function. |
force_await
async
¶
Takes a function, and if it needs awaiting, it will be awaited. If it is a synchronous function, it runs it in the event loop, preventing it from blocking.
This is equivalent to (pseudo):
Parameters:
Name | Type | Description | Default |
---|---|---|---|
function
|
Union[Callable, Coroutine]
|
The function to call. Make sure you do not call it, just pass it. |
required |
args
|
Any
|
The arguments to pass to the function. |
()
|
kwargs
|
Any
|
The keyword arguments to pass to the function. |
{}
|
Returns:
Type | Description |
---|---|
The result of the function. |