discord.ext.tasks

Added in version 1.1.0.

One of the most common operations when making a bot is having a loop run in the background at a specified interval. This pattern is very common but has a lot of things you need to look out for:

  • How do I handle asyncio.CancelledError?

  • What do I do if the internet goes out?

  • What is the maximum number of seconds I can sleep anyway?

The goal of this Pycord extension is to abstract all these worries away from you.

Recipes

A simple background task in a Cog:

from discord.ext import tasks, commands

class MyCog(commands.Cog):
    def __init__(self):
        self.index = 0
        self.printer.start()

    def cog_unload(self):
        self.printer.cancel()

    @tasks.loop(seconds=5.0)
    async def printer(self):
        print(self.index)
        self.index += 1

Adding an exception to handle during reconnect:

import asyncpg
from discord.ext import tasks, commands

class MyCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.data = []
        self.batch_update.add_exception_type(asyncpg.PostgresConnectionError)
        self.batch_update.start()

    def cog_unload(self):
        self.batch_update.cancel()

    @tasks.loop(minutes=5.0)
    async def batch_update(self):
        async with self.bot.pool.acquire() as con:
            # batch update here...
            pass

Looping a certain amount of times before exiting:

from discord.ext import tasks

@tasks.loop(seconds=5.0, count=5)
async def slow_count():
    print(slow_count.current_loop)

@slow_count.after_loop
async def after_slow_count():
    print('done!')

slow_count.start()

Waiting until the bot is ready before the loop starts:

from discord.ext import tasks, commands

class MyCog(commands.Cog):
    def __init__(self, bot):
        self.index = 0
        self.bot = bot
        self.printer.start()

    def cog_unload(self):
        self.printer.cancel()

    @tasks.loop(seconds=5.0)
    async def printer(self):
        print(self.index)
        self.index += 1

    @printer.before_loop
    async def before_printer(self):
        print('waiting...')
        await self.bot.wait_until_ready()

Doing something during cancellation:

from discord.ext import tasks, commands
import asyncio

class MyCog(commands.Cog):
    def __init__(self, bot):
        self.bot= bot
        self._batch = []
        self.lock = asyncio.Lock()
        self.bulker.start()

    async def do_bulk(self):
        # bulk insert data here
        ...

    @tasks.loop(seconds=10.0)
    async def bulker(self):
        async with self.lock:
            await self.do_bulk()

    @bulker.after_loop
    async def on_bulker_cancel(self):
        if self.bulker.is_being_cancelled() and len(self._batch) != 0:
            # if we're cancelled and we have some data left...
            # let's insert it to our database
            await self.do_bulk()

API Reference

class discord.ext.tasks.Loop(coro, seconds, hours, minutes, time, count, reconnect, loop, overlap)[kaynak]

A background task helper that abstracts the loop and reconnection logic for you.

The main interface to create this is through loop().

Parametreler:
@after_loop(coro)[kaynak]

A decorator that register a coroutine to be called after the loop finished running.

The coroutine must take no arguments (except self in a class context).

Not

This coroutine is called even during cancellation. If it is desirable to tell apart whether something was cancelled or not, check to see whether is_being_cancelled() is True or not.

Parametreler:

coro (TypeVar(FT, bound= Callable[..., Awaitable[Any]])) – The coroutine to register after the loop finishes.

Harekete geçirir:

TypeError – The function was not a coroutine.

Dönüş türü:

TypeVar(FT, bound= Callable[..., Awaitable[Any]])

@before_loop(coro)[kaynak]

A decorator that registers a coroutine to be called before the loop starts running.

This is useful if you want to wait for some bot state before the loop starts, such as discord.Client.wait_until_ready().

The coroutine must take no arguments (except self in a class context).

Parametreler:

coro (TypeVar(FT, bound= Callable[..., Awaitable[Any]])) – The coroutine to register before the loop runs.

Harekete geçirir:

TypeError – The function was not a coroutine.

Dönüş türü:

TypeVar(FT, bound= Callable[..., Awaitable[Any]])

@error(coro)[kaynak]

A decorator that registers a coroutine to be called if the task encounters an unhandled exception.

The coroutine must take only one argument the exception raised (except self in a class context).

By default, this prints to sys.stderr however it could be overridden to have a different implementation.

Added in version 1.4.

Parametreler:

coro (TypeVar(ET, bound= Callable[[Any, BaseException], Awaitable[Any]])) – The coroutine to register in the event of an unhandled exception.

Harekete geçirir:

TypeError – The function was not a coroutine.

Dönüş türü:

TypeVar(ET, bound= Callable[[Any, BaseException], Awaitable[Any]])

property seconds: float | None

Read-only value for the number of seconds between each iteration. None if an explicit time value was passed instead.

Added in version 2.0.

property minutes: float | None

Read-only value for the number of minutes between each iteration. None if an explicit time value was passed instead.

Added in version 2.0.

property hours: float | None

Read-only value for the number of hours between each iteration. None if an explicit time value was passed instead.

Added in version 2.0.

property time: list[time] | None

Read-only list for the exact times this loop runs at. None if relative times were passed instead.

Added in version 2.0.

property current_loop: int

The current iteration of the loop.

property next_iteration: datetime | None

When the next iteration of the loop will occur.

Added in version 1.3.

await __call__(*args, **kwargs)[kaynak]

This function is a coroutine.

Calls the internal callback that the task holds.

Added in version 1.6.

Parametreler:
  • *args (Any) – The arguments to use.

  • **kwargs (Any) – The keyword arguments to use.

Dönüş türü:

Any

start(*args, **kwargs)[kaynak]

Starts the internal task in the event loop.

Parametreler:
  • *args (Any) – The arguments to use.

  • **kwargs (Any) – The keyword arguments to use.

Harekete geçirir:

RuntimeError – A task has already been launched and is running.

Dönüşler:

The task that has been created.

Dönüş türü:

Task[None]

stop()[kaynak]

Gracefully stops the task from running.

Unlike cancel(), this allows the task to finish its current iteration before gracefully exiting.

Not

If the internal function raises an error that can be handled before finishing then it will retry until it succeeds.

If this is undesirable, either remove the error handling before stopping via clear_exception_types() or use cancel() instead.

Added in version 1.2.

Dönüş türü:

None

cancel()[kaynak]

Cancels the internal task, if it is running.

Dönüş türü:

None

restart(*args, **kwargs)[kaynak]

A convenience method to restart the internal task.

Not

Due to the way this function works, the task is not returned like start().

Parametreler:
  • *args (Any) – The arguments to use.

  • **kwargs (Any) – The keyword arguments to use.

Dönüş türü:

None

add_exception_type(*exceptions)[kaynak]

Adds exception types to be handled during the reconnect logic.

By default, the exception types handled are those handled by discord.Client.connect(), which includes a lot of internet disconnection errors.

This function is useful if you’re interacting with a 3rd party library that raises its own set of exceptions.

Parametreler:

*exceptions (type[BaseException]) – An argument list of exception classes to handle.

Harekete geçirir:

TypeError – An exception passed is either not a class or not inherited from BaseException.

Dönüş türü:

None

clear_exception_types()[kaynak]

Removes all exception types that are handled.

Not

This operation obviously cannot be undone!

Dönüş türü:

None

remove_exception_type(*exceptions)[kaynak]

Removes exception types from being handled during the reconnect logic.

Parametreler:

*exceptions (type[BaseException]) – An argument list of exception classes to handle.

Dönüşler:

Whether all exceptions were successfully removed.

Dönüş türü:

bool

get_task()[kaynak]

Fetches the internal task or None if there isn’t one running.

Dönüş türü:

Task[None] | None

is_being_cancelled()[kaynak]

Whether the task is being cancelled.

Dönüş türü:

bool

failed()[kaynak]

Whether the internal task has failed.

Added in version 1.2.

Dönüş türü:

bool

is_running()[kaynak]

Check if the task is currently running.

Added in version 1.4.

Dönüş türü:

bool

change_interval(*, seconds=0, minutes=0, hours=0, time=...)[kaynak]

Changes the interval for the sleep time.

Added in version 1.2.

Parametreler:
  • seconds (float) – The number of seconds between every iteration.

  • minutes (float) – The number of minutes between every iteration.

  • hours (float) – The number of hours between every iteration.

  • time (time | Sequence[time]) –

    The exact times to run this loop at. Either a non-empty list or a single value of datetime.time should be passed. This cannot be used in conjunction with the relative time parameters.

    Added in version 2.0.

    Not

    Duplicate times will be ignored, and only run once.

Harekete geçirir:
  • ValueError – An invalid value was given.

  • TypeError – An invalid value for the time parameter was passed, or the time parameter was passed in conjunction with relative time parameters.

Dönüş türü:

None

discord.ext.tasks.loop(*, seconds=..., minutes=..., hours=..., time=..., count=None, reconnect=True, loop=..., overlap=False)[kaynak]

A decorator that schedules a task in the background for you with optional reconnect logic. The decorator returns a Loop.

Parametreler:
  • seconds (float) – The number of seconds between every iteration.

  • minutes (float) – The number of minutes between every iteration.

  • hours (float) – The number of hours between every iteration.

  • time (time | Sequence[time]) –

    The exact times to run this loop at. Either a non-empty list or a single value of datetime.time should be passed. Timezones are supported. If no timezone is given for the times, it is assumed to represent UTC time.

    This cannot be used in conjunction with the relative time parameters.

    Not

    Duplicate times will be ignored, and only run once.

    Added in version 2.0.

  • count (int | None) – The number of loops to do, None if it should be an infinite loop.

  • reconnect (bool) – Whether to handle errors and restart the task using an exponential back-off algorithm similar to the one used in discord.Client.connect().

  • loop (AbstractEventLoop) – The loop to use to register the task, if not given the default event loop is used via asyncio.get_event_loop() if it exists or one is created via asyncio.new_event_loop().

  • overlap (bool | int) –

    Controls whether overlapping executions of the task loop are allowed. Set to False (default) to run iterations one at a time, True for unlimited overlap, or an int to cap the number of concurrent runs.

    Added in version 2.7.

Harekete geçirir:
  • ValueError – An invalid value was given.

  • TypeError – The function was not a coroutine, an invalid value for the time parameter was passed, or time parameter was passed in conjunction with relative time parameters.

Dönüş türü:

Callable[[TypeVar(LF, bound= Callable[..., Awaitable[Any]])], Loop[TypeVar(LF, bound= Callable[..., Awaitable[Any]])]]