Python 비동기 작업: 작업 사용 및 조회

작업은 비동기 프로그램의 화폐입니다. 본 절에서는 프로그램과의 상호작용 방법에 대해 자세히 알아보겠습니다.

  1. 작업 수명 주기

비동기 작업은 수명 주기를 가지고 있습니다. 먼저, 작업은 코루틴에서 생성됩니다. 그런 다음 이벤트 루프에 독립적으로 실행될 예약이 됩니다. 어느 순간에는 실행됩니다.

실행 중일 때 일시 중단될 수 있습니다. 예를 들어 다른 코루틴이나 작업을 기다릴 때. 정상적으로 완료되어 결과를 반환하거나 예외로 인해 실패할 수 있습니다.

다른 코루틴이 작업을 중단시킬 수 있습니다. 최종적으로 완료되고 다시 실행할 수 없습니다.

이 수명 주기를 아래와 같이 요약할 수 있습니다:

  1. 생성
  2. 예약
  3. 중단
  4. 실행
  5. 일시 중단
  6. 결과
  7. 예외
  8. 중단
  9. 완료

주목할 점은 Suspended, Result, Exception 및 Canceled는 상태가 아니라 실행 중인 작업의 중요한 전환점이라는 것입니다.

다음은 이 수명 주기를 요약한 도표입니다.

이 수명 주기를高层次로 알고 난 후, 각 단계를 자세히 살펴보겠습니다.

  1. 작업 상태 확인 방법

작업이 생성된 후, 작업의 상태를 확인할 수 있습니다. 확인할 두 가지 상태가 있습니다.

  • 작업이 완료되었는지
  • 작업이 중단되었는지

하나씩 차례대로 자세히 살펴보겠습니다.

2.1. 작업 완료 여부 확인

done() 메서드를 통해 작업이 완료되었는지 확인할 수 있습니다. 작업이 완료되면 이 메서드는 True를 반환합니다.

# 작업이 완료되었는지 확인
if 작업.done():
    # ...

작업이 실행할 기회가 있었지만 더 이상 실행 중이 아니면 완료되었습니다. 예약된 작업은 완료되지 않았습니다. 실행 중인 작업도 완료되지 않았습니다.

다음 중 하나가 발생하면 작업이 완료됩니다.

  1. 코루틴이 정상적으로 종료
  2. 코루틴에서 명시적으로 반환
  3. 코루틴에서 미사용 예외가 발생
  4. 작업이 중단

2.2. 작업 중단 여부 확인

cancelled() 메서드를 통해 작업이 중단되었는지 확인할 수 있습니다. 작업이 중단되면 이 메서드는 True를 반환합니다.

...
# 작업이 중단되었는지 확인
if 작업.cancelled():
    # ...

cancel() 메서드가 작업上调用되고 성공적으로 완료되면 작업이 중단됩니다.

cancel() 메서드가 호출되지 않았거나 호출되었지만 작업을 중단시키지 못하면 작업은 중단되지 않습니다.

  1. 작업 결과 가져오기

result() 메서드를 통해 작업의 결과를 가져올 수 있습니다. 이는 작업이 감싸고 있는 코루틴의 반환 값을 반환하며, 명시적으로 반환되지 않은 경우에는 None을 반환합니다.

...
# 작업에서 반환 값을 가져오기
값 = 작업.result()

작업이 예외를 일으켰다면 result() 메서드를 호출할 때 예외가 재발생되며 처리가 필요할 수 있습니다.

...
try:
    # 작업에서 반환 값을 가져오기
    값 = 작업.result()
except 예외:
    # 작업이 실패했고 결과가 없습니다

작업이 중단되었으면 result() 메서드를 호출할 때 CancelledError 예외가 발생할 수 있습니다.

...
try:
    # 작업에서 반환 값을 가져오기
    값 = 작업.result()
except asyncio.CancelledError:
    # 작업이 중단되었습니다

따라서 작업이 중단되었는지 먼저 확인하는 것이 좋습니다.

...
# 작업이 중단되지 않았는지 확인
if not 작업.cancelled():
    # 작업에서 반환 값을 가져오기
    값 = 작업.result()
else:
    # 작업이 중단되었습니다

작업이 완료되지 않았다면 result() 메서드를 호출할 때 InvalidStateError 예외가 발생할 수 있습니다.

...
try:
    # 작업에서 반환 값을 가져오기
    값 = 작업.result()
except asyncio.InvalidStateError:
    # 작업은 완료되지 않았습니다

따라서 작업이 완료되었는지 먼저 확인하는 것이 좋습니다.

...
# 작업이 완료되지 않았는지 확인
if not 작업.done():
    await 작업
# 작업에서 반환 값을 가져오기
값 = 작업.result()
  1. 작업 예외 가져오기

작업이 감싸고 있는 코루틴은 미사용 예외를 일으킬 수 있습니다. 이는 작업을 중단시킵니다.

exception() 메서드를 통해 작업에서 발생한 미사용 예외를 가져올 수 있습니다.

...
# 작업에서 발생한 예외 가져오기
예외 = 작업.exception()

미사용 예외가 없으면 None을 반환합니다.

작업이 중단되었으면 exception() 메서드를 호출할 때 CancelledError 예외가 발생할 수 있습니다.

...
try:
    # 작업에서 발생한 예외 가져오기
    예외 = 작업.exception()
except asyncio.CancelledError:
    # 작업이 중단되었습니다

따라서 작업이 중단되었는지 먼저 확인하는 것이 좋습니다.

...
# 작업이 중단되지 않았는지 확인
if not 작업.cancelled():
    # 작업에서 발생한 예외 가져오기
    예외 = 작업.exception()
else:
    # 작업이 중단되었습니다

작업이 완료되지 않았다면 exception() 메서드를 호출할 때 InvalidStateError 예외가 발생할 수 있습니다.

...
try:
    # 작업에서 발생한 예외 가져오기
    예외 = 작업.exception()
except asyncio.InvalidStateError:
    # 작업은 완료되지 않았습니다

따라서 작업이 완료되었는지 먼저 확인하는 것이 좋습니다.

...
# 작업이 완료되지 않았는지 확인
if not 작업.done():
    await 작업
# 작업에서 발생한 예외 가져오기
예외 = 작업.exception()
  1. 작업 중단 방법

cancel() 메서드를 통해 예약된 작업을 중단할 수 있습니다. 작업이 중단되면 cancel() 메서드는 True를 반환합니다.

...
# 작업을 중단합니다
was_cancelled = 작업.cancel()

작업이 이미 완료되었으면 중단할 수 없으며, cancel() 메서드는 False를 반환하며 작업은 중단되지 않습니다.

다음에 작업이 실행할 기회가 있을 때.CancelledError 예외가 발생합니다. 작업이 예외를 처리하지 않으면 작업이 중단됩니다. 예외를 처리하면 작업은 중단되지 않습니다.

cancel() 메서드는 또한 설명 메시지를 포함하는 매개변수를 받습니다.

  1. 작업에 콜백 함수 사용 방법

add_done_callback() 메서드를 통해 작업에 완료 콜백 함수를 추가할 수 있습니다. 이 메서드는 작업이 완료될 때 호출할 함수의 이름을 받습니다. 콜백 함수는 작업 인스턴스를 매개변수로 받습니다.

# 작업 완료 콜백 함수
def callback(작업):
    print(작업)
 
...
# 작업 완료 콜백 함수 등록
작업.add_done_callback(callback)

작업이 완료될 때, 감싸고 있는 코루틴이 정상적으로 반환, 미사용 예외를 일으키거나 중단될 때 콜백 함수가 호출됩니다.

add_done_callback() 메서드를 통해 여러 개의 콜백 함수를 등록할 수 있습니다.

콜백 함수를注销할 수 있도록 remove_done_callback() 함수도 있습니다.

...
# 작업 완료 콜백 함수注销
작업.remove_done_callback(callback)
  1. 작업 이름 설정 방법

작업에는 이름이 있을 수 있습니다. 여러 작업이 같은 코루틴에서 생성된 경우, 이 이름은 유용할 수 있습니다. 이름 매개변수를 사용해 작업을 생성할 수 있습니다.

...
# 코루틴에서 작업 생성
작업 = asyncio.create_task(task_coroutine(), name='작업명')

작업의 이름은 set_name() 메서드를 통해 변경할 수 있습니다.

...
# 작업 이름 설정
작업.set_name('작업명')

작업의 이름은 get_name() 메서드를 통해 가져올 수 있습니다.

...
# 작업 이름 가져오기
이름 = 작업.get_name()

이 문서는 여러 플랫폼에서 발행되었습니다.

태그: python 비동기 작업 관리

6월 16일 02:04에 게시됨