코루틴과 태스크

이 절에서는 코루틴과 태스크로 작업하기 위한 고급 asyncio API에 관해 설명합니다.

코루틴

async/await 문법으로 선언된 코루틴은 asyncio 응용 프로그램을 작성하는 기본 방법입니다. 예를 들어, 다음 코드 조각(파이썬 3.7 이상 필요)은 “hello”를 인쇄하고, 1초 동안 기다린 다음, “world”를 인쇄합니다:

>>> import asyncio

>>> async def main():
...     print('hello')
...     await asyncio.sleep(1)
...     print('world')

>>> asyncio.run(main())
hello
world

단지 코루틴을 호출하는 것으로 실행되도록 예약하는 것은 아닙니다:

>>> main()
<coroutine object main at 0x1053bb7c8>

코루틴을 실제로 실행하기 위해, asyncio가 세 가지 주요 메커니즘을 제공합니다:

  • 최상위 진입점 “main()” 함수를 실행하는 asyncio.run() 함수 (위의 예를 보세요.)

  • 코루틴을 기다리기. 다음 코드 조각은 1초를 기다린 후 “hello”를 인쇄한 다음 2초를 기다린 후 “world”를 인쇄합니다:

    import asyncio
    import time
    
    async def say_after(delay, what):
        await asyncio.sleep(delay)
        print(what)
    
    async def main():
        print(f"started at {time.strftime('%X')}")
    
        await say_after(1, 'hello')
        await say_after(2, 'world')
    
        print(f"finished at {time.strftime('%X')}")
    
    asyncio.run(main())
    

    예상 출력:

    started at 17:13:52
    hello
    world
    finished at 17:13:55
    
  • 코루틴을 asyncio 태스크로 동시에 실행하는 asyncio.create_task() 함수.

    위의 예를 수정해서 두 개의 say_after 코루틴을 동시에 실행해 봅시다:

    async def main():
        task1 = asyncio.create_task(
            say_after(1, 'hello'))
    
        task2 = asyncio.create_task(
            say_after(2, 'world'))
    
        print(f"started at {time.strftime('%X')}")
    
        # Wait until both tasks are completed (should take
        # around 2 seconds.)
        await task1
        await task2
    
        print(f"finished at {time.strftime('%X')}")
    

    예상 출력은 이제 코드 조각이 이전보다 1초 빠르게 실행되었음을 보여줍니다:

    started at 17:14:32
    hello
    world
    finished at 17:14:34
    

어웨이터블

우리는 객체가 await 표현식에서 사용될 수 있을 때 어웨이터블 객체라고 말합니다. 많은 asyncio API는 어웨이터블을 받아들이도록 설계되었습니다.

어웨이터블 객체에는 세 가지 주요 유형이 있습니다: 코루틴, 태스크퓨처.

코루틴

파이썬 코루틴은 어웨이터블이므로 다른 코루틴에서 기다릴 수 있습니다:

import asyncio

async def nested():
    return 42

async def main():
    # Nothing happens if we just call "nested()".
    # A coroutine object is created but not awaited,
    # so it *won't run at all*.
    nested()

    # Let's do it differently now and await it:
    print(await nested())  # will print "42".

asyncio.run(main())

중요

이 설명서에서 “코루틴” 이라는 용어는 두 가지 밀접한 관련 개념에 사용될 수 있습니다:

  • 코루틴 함수: async def 함수;

  • 코루틴 객체: 코루틴 함수를 호출하여 반환된 객체.

asyncio는 기존 제너레이터 기반 코루틴도 지원합니다.

태스크

태스크는 코루틴을 동시에 예약하는 데 사용됩니다.

코루틴이 asyncio.create_task()와 같은 함수를 사용하여 태스크로 싸일 때 코루틴은 곧 실행되도록 자동으로 예약됩니다:

import asyncio

async def nested():
    return 42

async def main():
    # Schedule nested() to run soon concurrently
    # with "main()".
    task = asyncio.create_task(nested())

    # "task" can now be used to cancel "nested()", or
    # can simply be awaited to wait until it is complete:
    await task

asyncio.run(main())

퓨처

Future는 비동기 연산의 최종 결과를 나타내는 특별한 저수준 어웨이터블 객체입니다.

Future 객체를 기다릴 때, 그것은 코루틴이 Future가 다른 곳에서 해결될 때까지 기다릴 것을 뜻합니다.

콜백 기반 코드를 async/await와 함께 사용하려면 asyncio의 Future 객체가 필요합니다.

일반적으로 응용 프로그램 수준 코드에서 Future 객체를 만들 필요는 없습니다.

때때로 라이브러리와 일부 asyncio API에 의해 노출되는 Future 객체를 기다릴 수 있습니다:

async def main():
    await function_that_returns_a_future_object()

    # this is also valid:
    await asyncio.gather(
        function_that_returns_a_future_object(),
        some_python_coroutine()
    )

Future 객체를 반환하는 저수준 함수의 좋은 예는 loop.run_in_executor()입니다.

asyncio 프로그램 실행하기

asyncio.run(coro, *, debug=False)

Execute the coroutine coro and return the result.

이 함수는 전달된 코루틴을 실행하고, asyncio 이벤트 루프와 비동기 제너레이터의 파이널리제이션을 관리합니다.

다른 asyncio 이벤트 루프가 같은 스레드에서 실행 중일 때, 이 함수를 호출할 수 없습니다.

debugTrue면, 이벤트 루프가 디버그 모드로 실행됩니다.

이 함수는 항상 새 이벤트 루프를 만들고 끝에 이벤트 루프를 닫습니다. asyncio 프로그램의 메인 진입 지점으로 사용해야 하고, 이상적으로는 한 번만 호출해야 합니다.

예:

async def main():
    await asyncio.sleep(1)
    print('hello')

asyncio.run(main())

버전 3.7에 추가: 중요: 이 함수는 파이썬 3.7에서 잠정적으로 asyncio에 추가되었습니다.

태스크 만들기

asyncio.create_task(coro)

coro 코루틴Task로 감싸고 실행을 예약합니다. Task 객체를 반환합니다.

get_running_loop()에 의해 반환된 루프에서 태스크가 실행되고, 현재 스레드에 실행 중인 루프가 없으면 RuntimeError가 발생합니다.

이 함수는 파이썬 3.7에서 추가되었습니다. 파이썬 3.7 이전 버전에서는, 대신 저수준 asyncio.ensure_future() 함수를 사용할 수 있습니다:

async def coro():
    ...

# In Python 3.7+
task = asyncio.create_task(coro())
...

# This works in all Python versions but is less readable
task = asyncio.ensure_future(coro())
...

버전 3.7에 추가.

잠자기

coroutine asyncio.sleep(delay, result=None, *, loop=None)

delay 초 동안 블록합니다.

result가 제공되면, 코루틴이 완료될 때 호출자에게 반환됩니다.

sleep()은 항상 현재 태스크를 일시 중단해서 다른 태스크를 실행할 수 있도록 합니다.

loop 인자는 폐지되었고 파이썬 3.10에서 삭제 예정입니다.

5초 동안 현재 날짜를 매초 표시하는 코루틴의 예:

import asyncio
import datetime

async def display_date():
    loop = asyncio.get_running_loop()
    end_time = loop.time() + 5.0
    while True:
        print(datetime.datetime.now())
        if (loop.time() + 1.0) >= end_time:
            break
        await asyncio.sleep(1)

asyncio.run(display_date())

동시에 태스크 실행하기

awaitable asyncio.gather(*aws, loop=None, return_exceptions=False)

aws 시퀀스에 있는 어웨이터블 객체동시에 실행합니다.

aws에 있는 어웨이터블이 코루틴이면 자동으로 태스크로 예약됩니다.

모든 어웨이터블이 성공적으로 완료되면, 결과는 반환된 값들이 합쳐진 리스트입니다. 결괏값의 순서는 aws에 있는 어웨이터블의 순서와 일치합니다.

return_exceptionsFalse(기본값)면, 첫 번째 발생한 예외가 gather()를 기다리는 태스크로 즉시 전파됩니다. aws 시퀀스의 다른 어웨이터블은 취소되지 않고 계속 실행됩니다.

return_exceptionsTrue면, 예외는 성공적인 결과처럼 처리되고, 결과 리스트에 집계됩니다.

gather()취소되면, 모든 제출된 (아직 완료되지 않은) 어웨이터블도 취소됩니다.

aws 시퀀스의 Task나 Future가 취소되면, 그것이 CancelledError를 일으킨 것처럼 처리됩니다 – 이때 gather() 호출은 취소되지 않습니다. 이것은 제출된 태스크/퓨처 하나를 취소하는 것이 다른 태스크/퓨처를 취소하게 되는 것을 막기 위한 것입니다.

예:

import asyncio

async def factorial(name, number):
    f = 1
    for i in range(2, number + 1):
        print(f"Task {name}: Compute factorial({i})...")
        await asyncio.sleep(1)
        f *= i
    print(f"Task {name}: factorial({number}) = {f}")

async def main():
    # Schedule three calls *concurrently*:
    await asyncio.gather(
        factorial("A", 2),
        factorial("B", 3),
        factorial("C", 4),
    )

asyncio.run(main())

# Expected output:
#
#     Task A: Compute factorial(2)...
#     Task B: Compute factorial(2)...
#     Task C: Compute factorial(2)...
#     Task A: factorial(2) = 2
#     Task B: Compute factorial(3)...
#     Task C: Compute factorial(3)...
#     Task B: factorial(3) = 6
#     Task C: Compute factorial(4)...
#     Task C: factorial(4) = 24

버전 3.7에서 변경: gather 자체가 취소되면, return_exceptions와 관계없이 취소가 전파됩니다.

취소로부터 보호하기

awaitable asyncio.shield(aw, *, loop=None)

어웨이터블 객체취소로부터 보호합니다.

aw가 코루틴이면 자동으로 태스크로 예약됩니다.

다음 문장:

res = await shield(something())

은 다음과 동등합니다:

res = await something()

, 그것을 포함하는 코루틴이 취소되면, something()에서 실행 중인 태스크는 취소되지 않는다는 것만 예외입니다. something()의 관점에서는, 취소가 일어나지 않았습니다. 호출자는 여전히 취소되었고, “await” 표현식은 여전히 CancelledError를 발생시킵니다.

something()가 다른 수단(즉, 그 안에서 스스로)에 의해 취소되면, shield()도 취소됩니다.

취소를 완전히 무시하려면(권장되지 않습니다), 다음과 같이 shield() 함수를 try/except 절과 결합해야 합니다:

try:
    res = await shield(something())
except CancelledError:
    res = None

시간제한

coroutine asyncio.wait_for(aw, timeout, *, loop=None)

aw 어웨이터블이 제한된 시간 내에 완료될 때까지 기다립니다.

aw가 코루틴이면 자동으로 태스크로 예약됩니다.

timeoutNone 또는 대기할 float 나 int 초 수입니다. timeoutNone이면 퓨처가 완료될 때까지 블록합니다.

시간 초과가 발생하면, 태스크를 취소하고 asyncio.TimeoutError를 발생시킵니다.

태스크 취소를 피하려면, shield()로 감싸십시오.

이 함수는 퓨처가 실제로 취소될 때까지 대기하므로, 총 대기 시간이 timeout을 초과할 수 있습니다.

대기가 취소되면, 퓨처 aw도 취소됩니다.

loop 인자는 폐지되었고 파이썬 3.10에서 삭제 예정입니다.

예:

async def eternity():
    # Sleep for one hour
    await asyncio.sleep(3600)
    print('yay!')

async def main():
    # Wait for at most 1 second
    try:
        await asyncio.wait_for(eternity(), timeout=1.0)
    except asyncio.TimeoutError:
        print('timeout!')

asyncio.run(main())

# Expected output:
#
#     timeout!

버전 3.7에서 변경: 시간 초과로 인해 aw가 취소되면, wait_foraw가 취소될 때까지 대기합니다. 이전에는 asyncio.TimeoutError가 즉시 발생했습니다.

대기 프리미티브

coroutine asyncio.wait(aws, *, loop=None, timeout=None, return_when=ALL_COMPLETED)

aws 집합에 있는 어웨이터블 객체를 동시에 실행하고, return_when에 의해 지정된 조건을 만족할 때까지 블록합니다.

aws에 있는 어웨이터블이 코루틴이면, 자동으로 태스크로 예약됩니다. 코루틴 객체를 wait()로 직접 전달하는 것은 혼란스러운 동작으로 연결되므로 폐지되었습니다.

두 집합의 태스크/퓨처를 반환합니다: (done, pending).

사용법:

done, pending = await asyncio.wait(aws)

loop 인자는 폐지되었고 파이썬 3.10에서 삭제 예정입니다.

timeout(float나 int)을 지정하면, 반환하기 전에 대기할 최대 시간(초)을 제어할 수 있습니다.

이 함수는 asyncio.TimeoutError를 발생시키지 않음에 유의하십시오. 시간 초과가 발생할 때 완료되지 않은 퓨처나 태스크는 단순히 두 번째 집합으로 반환됩니다.

return_when는 이 함수가 언제 반환해야 하는지 나타냅니다. 다음 상수 중 하나여야 합니다:

상수

설명

FIRST_COMPLETED

퓨처가 하나라도 끝나거나 취소될 때 함수가 반환됩니다.

FIRST_EXCEPTION

퓨처가 하나라도 예외를 일으켜 끝나면 함수가 반환됩니다. 어떤 퓨처도 예외를 일으키지 않으면 ALL_COMPLETED와 같습니다.

ALL_COMPLETED

모든 퓨처가 끝나거나 취소되면 함수가 반환됩니다.

wait_for()와 달리, wait()는 시간 초과가 발생할 때 퓨처를 취소하지 않습니다.

참고

wait()는 코루틴을 태스크로 자동 예약하고, 나중에 묵시적으로 생성된 Task 객체를 (done, pending) 집합으로 반환합니다. 따라서 다음 코드는 기대한 대로 작동하지 않습니다:

async def foo():
    return 42

coro = foo()
done, pending = await asyncio.wait({coro})

if coro in done:
    # This branch will never be run!

위의 조각을 고치는 방법은 다음과 같습니다:

async def foo():
    return 42

task = asyncio.create_task(foo())
done, pending = await asyncio.wait({task})

if task in done:
    # Everything will work as expected now.

코루틴 객체를 wait()로 직접 전달하는 것은 폐지되었습니다.

asyncio.as_completed(aws, *, loop=None, timeout=None)

aws 집합에 있는 어웨이터블 객체를 동시에 실행합니다. Future 객체의 이터레이터를 반환합니다. 반환된 각 Future 객체는 남아있는 어웨이터블 집합의 가장 빠른 결과를 나타냅니다.

모든 퓨처가 완료되기 전에 시간 초과가 발생하면 asyncio.TimeoutError를 발생시킵니다.

예:

for f in as_completed(aws):
    earliest_result = await f
    # ...

다른 스레드에서 예약하기

asyncio.run_coroutine_threadsafe(coro, loop)

주어진 이벤트 루프에 코루틴을 제출합니다. 스레드 안전합니다.

다른 OS 스레드에서 결과를 기다리는 concurrent.futures.Future를 반환합니다.

이 함수는 이벤트 루프가 실행 중인 스레드가 아닌, 다른 OS 스레드에서 호출하기 위한 것입니다. 예:

# Create a coroutine
coro = asyncio.sleep(1, result=3)

# Submit the coroutine to a given loop
future = asyncio.run_coroutine_threadsafe(coro, loop)

# Wait for the result with an optional timeout argument
assert future.result(timeout) == 3

코루틴에서 예외가 발생하면, 반환된 Future에 통지됩니다. 또한, 이벤트 루프에서 태스크를 취소하는 데 사용할 수 있습니다:

try:
    result = future.result(timeout)
except asyncio.TimeoutError:
    print('The coroutine took too long, cancelling the task...')
    future.cancel()
except Exception as exc:
    print(f'The coroutine raised an exception: {exc!r}')
else:
    print(f'The coroutine returned: {result!r}')

설명서의 동시성과 다중 스레드 절을 참조하십시오.

다른 asyncio 함수와 달리, 이 함수는 loop 인자가 명시적으로 전달되어야 합니다.

버전 3.5.1에 추가.

인트로스팩션

asyncio.current_task(loop=None)

현재 실행 중인 Task 인스턴스를 반환하거나 태스크가 실행되고 있지 않으면 None을 반환합니다.

loopNone이면, 현재 루프를 가져오는 데 get_running_loop()가 사용됩니다.

버전 3.7에 추가.

asyncio.all_tasks(loop=None)

루프에 의해 실행되는 아직 완료되지 않은 Task 객체 집합을 반환합니다.

loopNone이면, 현재 루프를 가져오는 데 get_running_loop()가 사용됩니다.

버전 3.7에 추가.

Task 객체

class asyncio.Task(coro, *, loop=None)

파이썬 코루틴을 실행하는 퓨처류 객체입니다. 스레드 안전하지 않습니다.

태스크는 이벤트 루프에서 코루틴을 실행하는 데 사용됩니다. 만약 코루틴이 Future를 기다리고 있다면, 태스크는 코루틴의 실행을 일시 중지하고 Future의 완료를 기다립니다. 퓨처가 완료되면, 감싸진 코루틴의 실행이 다시 시작됩니다.

이벤트 루프는 협업 스케줄링을 사용합니다: 이벤트 루프는 한 번에 하나의 Task를 실행합니다. Task가 Future의 완료를 기다리는 동안, 이벤트 루프는 다른 태스크, 콜백을 실행하거나 IO 연산을 수행합니다.

테스트를 만들려면 고수준 asyncio.create_task() 함수를 사용하거나, 저수준 loop.create_task()ensure_future() 함수를 사용하십시오. 태스크의 인스턴스를 직접 만드는 것은 권장되지 않습니다.

실행 중인 Task를 취소하려면 cancel() 메서드를 사용하십시오. 이를 호출하면 태스크가 감싼 코루틴으로 CancelledError 예외를 던집니다. 코루틴이 취소 중에 Future 객체를 기다리고 있으면, Future 객체가 취소됩니다.

cancelled()는 태스크가 취소되었는지 확인하는 데 사용할 수 있습니다. 이 메서드는 감싼 코루틴이 CancelledError 예외를 억제하지 않고 실제로 취소되었으면 True를 반환합니다.

asyncio.TaskFuture.set_result()Future.set_exception()을 제외한 모든 API를 Future에서 상속받습니다.

태스크는 contextvars 모듈을 지원합니다. 태스크가 만들어질 때 현재 컨텍스트를 복사하고 나중에 복사된 컨텍스트에서 코루틴을 실행합니다.

버전 3.7에서 변경: contextvars 모듈에 대한 지원이 추가되었습니다.

cancel()

Task 취소를 요청합니다.

이벤트 루프의 다음 사이클에서 감싼 코루틴으로 CancelledError 예외를 던져넣도록 합니다.

그러면 코루틴은 try … … except CancelledErrorfinally 블록으로 정리하거나 예외를 억제하여 요청을 거부할 수 있습니다. 따라서, Future.cancel()와 달리 Task.cancel()은 Task가 취소됨을 보장하지는 않습니다. 하지만 취소를 완전히 억제하는 것은 일반적이지 않고, 그렇게 하지 말도록 적극적으로 권합니다.

다음 예는 코루틴이 취소 요청을 가로채는 방법을 보여줍니다:

async def cancel_me():
    print('cancel_me(): before sleep')

    try:
        # Wait for 1 hour
        await asyncio.sleep(3600)
    except asyncio.CancelledError:
        print('cancel_me(): cancel sleep')
        raise
    finally:
        print('cancel_me(): after sleep')

async def main():
    # Create a "cancel_me" Task
    task = asyncio.create_task(cancel_me())

    # Wait for 1 second
    await asyncio.sleep(1)

    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        print("main(): cancel_me is cancelled now")

asyncio.run(main())

# Expected output:
#
#     cancel_me(): before sleep
#     cancel_me(): cancel sleep
#     cancel_me(): after sleep
#     main(): cancel_me is cancelled now
cancelled()

Task가 취소(cancelled)되었으면 True를 반환합니다.

Task는 cancel()로 취소가 요청되고 감싼 코루틴이 자신에게 전달된 CancelledError 예외를 확산할 때 최소(cancelled)됩니다.

done()

Task가 완료(done)되었으면 True를 반환합니다.

감싼 코루틴이 값을 반환하거나 예외를 일으키거나, Task가 취소되면 Task는 완료(done)됩니다.

result()

Task의 결과를 반환합니다.

Task가 완료(done)되었으면 감싼 코루틴의 결과가 반환됩니다 (또는 코루틴이 예외를 발생시켰으면 해당 예외가 다시 발생합니다).

태스크가 취소(cancelled)되었으면, 이 메서드는 CancelledError 예외를 발생시킵니다.

태스크 결과를 아직 사용할 수 없으면, 이 메서드는 InvalidStateError 예외를 발생시킵니다.

exception()

Task의 예외를 반환합니다.

감싼 코루틴이 예외를 발생시키면, 그 예외가 반환됩니다. 감싼 코루틴이 정상적으로 반환되면, 이 메서드는 None을 반환합니다.

태스크가 취소(cancelled)되었으면, 이 메서드는 CancelledError 예외를 발생시킵니다.

태스크가 아직 완료(done)되지 않았으면, 이 메서드는 InvalidStateError 예외를 발생시킵니다.

add_done_callback(callback, *, context=None)

태스크가 완료(done)될 때 실행할 콜백을 추가합니다.

이 메서드는 저수준 콜백 기반 코드에서만 사용해야 합니다.

자세한 내용은 Future.add_done_callback() 설명서를 참조하십시오.

remove_done_callback(callback)

콜백 목록에서 callback을 제거합니다.

이 메서드는 저수준 콜백 기반 코드에서만 사용해야 합니다.

자세한 내용은 Future.remove_done_callback() 설명서를 참조하십시오.

get_stack(*, limit=None)

이 Task의 스택 프레임 리스트를 돌려줍니다.

감싼 코루틴이 완료되지 않았으면, 일시 정지된 곳의 스택을 반환합니다. 코루틴이 성공적으로 완료되었거나 취소되었으면 빈 리스트가 반환됩니다. 코루틴이 예외로 종료되었으면, 이것은 트레이스백 프레임의 리스트를 반환합니다.

프레임은 항상 가장 오래된 것부터 순서대로 정렬됩니다.

일시 정지된 코루틴에서는 하나의 스택 프레임만 반환됩니다.

선택적 limit 인자는 반환할 최대 프레임 수를 설정합니다; 기본적으로 사용 가능한 모든 프레임이 반환됩니다. 반환되는 리스트의 순서는 스택과 트레이스백 중 어느 것이 반환되는지에 따라 다릅니다: 스택은 최신 프레임이 반환되지만, 트레이스백은 가장 오래된 프레임이 반환됩니다. (이는 traceback 모듈의 동작과 일치합니다.)

print_stack(*, limit=None, file=None)

이 Task의 스택이나 트레이스백을 인쇄합니다.

이것은 get_stack()으로 얻은 프레임에 대해 traceback 모듈과 유사한 출력을 생성합니다.

limit 인자는 get_stack()에 직접 전달됩니다.

file 인자는 출력이 기록되는 I/O 스트림입니다; 기본적으로 출력은 sys.stderr에 기록됩니다.

classmethod all_tasks(loop=None)

이벤트 루프의 모든 태스크 집합을 돌려줍니다.

기본적으로 현재 이벤트 루프에 대한 모든 태스크가 반환됩니다. loopNone이면, 현재 루프를 가져오는 데 get_event_loop() 함수가 사용됩니다.

이 메서드는 폐지되었고 파이썬 3.9에서 제거됩니다. asyncio.all_tasks() 함수를 대신 사용하십시오.

classmethod current_task(loop=None)

현재 실행 중인 태스크나 None을 반환합니다.

loopNone이면, 현재 루프를 가져오는 데 get_event_loop() 함수가 사용됩니다.

이 메서드는 폐지되었고 파이썬 3.9에서 제거됩니다. asyncio.current_task() 함수를 대신 사용하십시오.

제너레이터 기반 코루틴

참고

제너레이터 기반 코루틴에 대한 지원은 폐지되었고 파이썬 3.10에서 삭제될 예정입니다.

제너레이터 기반 코루틴은 async/await 문법 전에 나왔습니다. 퓨처와 다른 코루틴을 기다리기 위해 yield from 표현식을 사용하는 파이썬 제너레이터입니다.

제너레이터 기반 코루틴은 @asyncio.coroutine으로 데코레이트 되어야 하지만 강제되지는 않습니다.

@asyncio.coroutine

제너레이터 기반 코루틴을 표시하는 데코레이터.

이 데코레이터는 기존 제너레이터 기반 코루틴이 async/await 코드와 호환되도록 합니다:

@asyncio.coroutine
def old_style_coroutine():
    yield from asyncio.sleep(1)

async def main():
    await old_style_coroutine()

이 데코레이터는 폐지되었고 파이썬 3.10에서 삭제 예정입니다.

async def 코루틴에는 이 데코레이터를 사용하면 안 됩니다.

asyncio.iscoroutine(obj)

obj코루틴 객체True를 반환합니다.

이 메서드는 제너레이터 기반 코루틴에 대해 True를 반환하기 때문에, inspect.iscoroutine()과 다릅니다.

asyncio.iscoroutinefunction(func)

func코루틴 함수True를 반환합니다.

이 메서드는 @coroutine으로 데코레이트 된 제너레이터 기반 코루틴 함수에 대해 True를 반환하기 때문에, inspect.iscoroutinefunction()과 다릅니다.