discord.ext.tasks – asyncio.Task 헬퍼

버전 1.1.0에 추가.

봇을 만들 때 하는 가장 흔한 작업은 특정한 간격으로 백그라운드에서 돌아가는 루프를 갖는 것입니다. 이 패턴은 매우 흔하지만 당신이 조심해야할 많은 것들이 있습니다:

  • asyncio.CancelledError 는 어떻게 다루나요?

  • 만약에 인터넷이 끊기면 어떻게 해야하나요?

  • 아무튼 제가 잘 수 있는 최고 시간은 몇초인가요?

이 discord.py 확장의 목적은 이런 관념적인 걱정들을 덜어주는 것입니다.

레시피

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

재연결 중 발생하는 예외를 처리하기 위해 예외 추가:

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

종료하기 전에 특정 개수만큼 반복:

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()

루프를 시작하기 전에 봇이 준비되기 전까지 기다림:

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()

취소하는 동안 무언가를 하기:

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 레퍼런스

class discord.ext.tasks.Loop

당신을 위해 루프와 재연결 로직을 추상화하는 백그라운드 태스크 헬퍼.

이것을 생성하는 주요 인터페이스는 loop() 를 통한 것입니다.

current_loop

루프의 현재 반복 중인 곳.

형식

int

next_iteration

루프의 다음 반복이 일어날 때

버전 1.3에 추가.

형식

옵션[datetime.datetime]

await __call__(*args, **kwargs)

이 함수는 코루틴 입니다.

Calls the internal callback that the task holds.

버전 1.6에 추가.

매개변수
  • *args – 사용할 전달인자.

  • **kwargs – 사용할 키워드 전달인자.

start(*args, **kwargs)

이벤트 루프에서 내부 태스크를 시작합니다.

매개변수
  • *args – 사용할 전달인자.

  • **kwargs – 사용할 키워드 전달인자.

예외

RuntimeError – 태스크가 이미 시작되었고 실행되는 중입니다.

반환값

생성된 태스크.

반환 형식

asyncio.Task

stop()

돌아가는 태스크를 중지합니다.

cancel()과는 달리, 태스크를 중지하기 전에 현재 반복 중인 것을 완료하게 만듭니다.

참고

만약 내부 함수가 끝내기 전에 처리할 수 있는 오류를 일으켰다면 성공할 때 까지 재시도할 것입니다.

만약에 이것을 원하지 않는다면, clear_exception_types()로 멈추기 전에 오류 처리를 제거하거나 cancel()을 대신 사용해주세요.

버전 1.2에 추가.

cancel()

약 내부 태스크가 돌아가고 있다면 취소함.》

restart(*args, **kwargs)

내부 태스크를 재시작하기 위한 편리한 방법.

참고

이 함수가 작동하는 방식 때문에, start()처럼 태스크가 반환되지 않습니다.

매개변수
  • *args – 사용할 전달인자.

  • **kwargs – 사용할 키워드 전달인자.

add_exception_type(*exceptions)

재연결 로직 도중 처리돼야 하는 예외 형식들을 추가합니다.

기본 상태에서는 처리되는 예외 형식들은 discord.Client.connect()로 처리되는데, 많은 인터넷 연결 끊어짐 오류를 포함하고 있습니다.

만약에 자기만의 예외 집합을 일으키는 제 3자 라이브러리와 상호 작용하고 있다면 이 함수는 유용합니다.

매개변수

*exceptions (Type[BaseException]) – 처리해야 할 예외 클래스들의 전달인자 리스트.

예외

TypeError – 지나간 예외는 클래스가 아니거나 BaseException에서 상속되지 않았습니다.

clear_exception_types()

처리 가능한 모든 형식의 예외를 삭제합니다.

참고

이 작업은 당연히 되돌릴 수 없습니다!

remove_exception_type(*exceptions)

재연결 로직 도중 처리돼야 하는 예외 형식들을 삭제합니다.

매개변수

*exceptions (Type[BaseException]) – 처리해야 할 예외 클래스들의 전달인자 리스트.

반환값

모든 예외가 성공적으로 삭제되었는지의 여부.

반환 형식

bool

get_task()

옵션[asyncio.Task]: 내부 테스크를 가져오거나 아무것도 돌아가고 있지 않는다면 None을 반환합니다.

is_being_cancelled()

태스크가 취소되고 있는지의 여부.

failed()

bool: 내부 테스크가 실패했는지의 여부.

버전 1.2에 추가.

is_running()

bool: 태스크가 돌아가고 있는지 확인합니다.

버전 1.4에 추가.

before_loop(coro)

루프가 시작되기 전에 코루틴이 호출되도록 등록하는 데코레이터.

만약에 discord.Client.wait_until_ready()처럼 루프가 시작되기 전에 몇가지 봇 상태가 기다리도록 만들고 싶다면 유용합니다.

코루틴은 (클래스 컨택스트 내부에 있는 self를 제외하고) 그 어떤 전달인자도 갖고 있으면 안됩니다.

매개변수

coro (coroutine) – 루프가 시작되기 전에 등록할 코루틴.

예외

TypeError – 함수가 코루틴이 아닙니다.

after_loop(coro)

루프가 끝난 이후 코루틴이 호출되도록 등록하는 데코레이터.

코루틴은 (클래스 컨택스트 내부에 있는 self를 제외하고) 그 어떤 전달인자도 갖고 있으면 안됩니다.

참고

이 코루틴은 취소할때도 호출됩니다. 만약에 무언가가 취소되었는지 아닌지를 분리해야 한다면, is_being_cancelled()True인지 아닌지를 확인하세요.

매개변수

coro (coroutine) – 루프가 끝난 후 등록할 코루틴.

예외

TypeError – 함수가 코루틴이 아닙니다.

error(coro)

만약 테스크가 처리되지 않은 예외를 만났을 경우 호출될 코루틴을 등록하는 데코레이터.

코루틴은 (클래스 컨택스트 내부에 있는 self를 제외하고) 발생한 예외 전달인자 하나만을 가져야 합니다.

기본 상태에서는 sys.stderr로 출력하지만 다른 구현을 가지기 위해 무시될 수 있습니다.

버전 1.4에 추가.

매개변수

coro (coroutine) – 처리되지 않은 예외 이벤트에서 등록할 코루틴.

예외

TypeError – 함수가 코루틴이 아닙니다.

change_interval(*, seconds=0, minutes=0, hours=0)

슬립 시간 간격을 변경합니다.

참고

이것은 다음 루프 반복에서만 적용됩니다. 만약 간격 변경이 바로 적용되기를 원한다면, cancel()로 태스크를 취소하세요.

버전 1.2에 추가.

매개변수
  • seconds (float) – 모든 반복 사이의 초.

  • minutes (float) – 모든 반복 사이의 분.

  • hours (float) – 모든 반복 사이의 시간.

예외

ValueError – 잘못된 값이 주어졌습니다.

discord.ext.tasks.loop(*, seconds=0, minutes=0, hours=0, count=None, reconnect=True, loop=None)

재연결 로직 옵션과 백그라운드에서 태스크를 예약하는 데코레이터. 데코레이터는 Loop를 반환합니다.

매개변수
  • seconds (float) – 모든 반복 사이의 초.

  • minutes (float) – 모든 반복 사이의 분.

  • hours (float) – 모든 반복 사이의 시간.

  • count (Optional[int]) – 루프의 반복 횟수, 만약에 무한 반복이어야 한다면 None.

  • reconnect (bool) – discord.Client.connect()에 사용된 것처럼 기하급수적인 백오프 알고리즘으로 오류를 처리하거나 태스크를 재시작할지의 여부

  • loop (asyncio.AbstractEventLoop) – 태스크를 등록하기 위해 사용하는 루프, 만약에 주어지지 않았다면 기본으로 asyncio.get_event_loop().

예외
  • ValueError – 잘못된 값이 주어졌습니다.

  • TypeError – 함수가 코루틴이 아닙니다.