mirror of
				https://github.com/Rapptz/discord.py.git
				synced 2025-11-04 07:22:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			213 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
.. _discord_ext_tasks:
 | 
						|
 | 
						|
``discord.ext.tasks`` -- asyncio.Task helpers
 | 
						|
====================================================
 | 
						|
 | 
						|
.. versionadded:: 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 :exc:`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 discord.py extension is to abstract all these worries away from you.
 | 
						|
 | 
						|
Recipes
 | 
						|
---------
 | 
						|
 | 
						|
A simple background task in a :class:`~discord.ext.commands.Cog`:
 | 
						|
 | 
						|
.. code-block:: python3
 | 
						|
 | 
						|
    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:
 | 
						|
 | 
						|
.. code-block:: python3
 | 
						|
 | 
						|
    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:
 | 
						|
 | 
						|
.. code-block:: python3
 | 
						|
 | 
						|
    from discord.ext import tasks
 | 
						|
    import discord
 | 
						|
 | 
						|
    @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!')
 | 
						|
 | 
						|
    class MyClient(discord.Client):
 | 
						|
        async def setup_hook(self):
 | 
						|
            slow_count.start()
 | 
						|
 | 
						|
Waiting until the bot is ready before the loop starts:
 | 
						|
 | 
						|
.. code-block:: python3
 | 
						|
 | 
						|
    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:
 | 
						|
 | 
						|
.. code-block:: python3
 | 
						|
 | 
						|
    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 cog_unload(self):
 | 
						|
            self.bulker.cancel()
 | 
						|
 | 
						|
        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()
 | 
						|
 | 
						|
Doing something at a specific time each day:
 | 
						|
 | 
						|
.. code-block:: python3
 | 
						|
 | 
						|
    import datetime
 | 
						|
    from discord.ext import commands, tasks
 | 
						|
 | 
						|
    utc = datetime.timezone.utc
 | 
						|
 | 
						|
    # If no tzinfo is given then UTC is assumed.
 | 
						|
    time = datetime.time(hour=8, minute=30, tzinfo=utc)
 | 
						|
 | 
						|
    class MyCog(commands.Cog):
 | 
						|
        def __init__(self, bot):
 | 
						|
            self.bot = bot
 | 
						|
            self.my_task.start()
 | 
						|
 | 
						|
        def cog_unload(self):
 | 
						|
            self.my_task.cancel()
 | 
						|
 | 
						|
        @tasks.loop(time=time)
 | 
						|
        async def my_task(self):
 | 
						|
            print("My task is running!")
 | 
						|
 | 
						|
Doing something at multiple specific times each day:
 | 
						|
 | 
						|
.. code-block:: python3
 | 
						|
 | 
						|
    import datetime
 | 
						|
    from discord.ext import commands, tasks
 | 
						|
 | 
						|
    utc = datetime.timezone.utc
 | 
						|
 | 
						|
    # If no tzinfo is given then UTC is assumed.
 | 
						|
    times = [
 | 
						|
        datetime.time(hour=8, tzinfo=utc),
 | 
						|
        datetime.time(hour=12, minute=30, tzinfo=utc),
 | 
						|
        datetime.time(hour=16, minute=40, second=30, tzinfo=utc)
 | 
						|
    ]
 | 
						|
 | 
						|
    class MyCog(commands.Cog):
 | 
						|
        def __init__(self, bot):
 | 
						|
            self.bot = bot
 | 
						|
            self.my_task.start()
 | 
						|
 | 
						|
        def cog_unload(self):
 | 
						|
            self.my_task.cancel()
 | 
						|
 | 
						|
        @tasks.loop(time=times)
 | 
						|
        async def my_task(self):
 | 
						|
            print("My task is running!")
 | 
						|
 | 
						|
.. _ext_tasks_api:
 | 
						|
 | 
						|
API Reference
 | 
						|
---------------
 | 
						|
 | 
						|
.. attributetable:: discord.ext.tasks.Loop
 | 
						|
 | 
						|
.. autoclass:: discord.ext.tasks.Loop()
 | 
						|
    :members:
 | 
						|
    :special-members: __call__
 | 
						|
    :exclude-members: after_loop, before_loop, error
 | 
						|
 | 
						|
    .. automethod:: Loop.after_loop()
 | 
						|
        :decorator:
 | 
						|
 | 
						|
    .. automethod:: Loop.before_loop()
 | 
						|
        :decorator:
 | 
						|
 | 
						|
    .. automethod:: Loop.error()
 | 
						|
        :decorator:
 | 
						|
 | 
						|
.. autofunction:: discord.ext.tasks.loop
 | 
						|
    :decorator:
 |