실행자(Runners)¶
소스 코드: Lib/asyncio/runners.py
이 섹션에서는 asyncio 코드를 실행하기 위한 고수준 asyncio 프리미티브를 설명합니다.
이들은 일반적이고 널리 사용되는 시나리오에서 비동기 코드 사용을 간소화하는 것을 목표로 하며, 이벤트 루프 를 기반으로 구축되었습니다.
asyncio 프로그램 실행¶
- asyncio.run(coro, *, debug=None, loop_factory=None)¶
asyncio 이벤트 루프에서 coro 를 실행하고 그 결과를 반환합니다.
인자는 모든 어웨이터블(awaitable) 객체일 수 있습니다.
이 함수는 어웨이터블을 실행하며, asyncio 이벤트 루프 관리, 비동기 제너레이터의 파이널리제이션, 및 실행기(executor)를 닫는 과정을 처리합니다.
다른 asyncio 이벤트 루프가 동일한 스레드에서 실행 중일 때 이 함수를 호출할 수 없습니다.
debug 가
True이면 이벤트 루프가 디버그 모드로 실행됩니다.False는 디버그 모드를 명시적으로 비활성화합니다.None은 전역 디버그 모드 설정을 따릅니다.loop_factory 가
None이 아니면 새로운 이벤트 루프를 생성하는 데 사용되며, 그렇지 않으면asyncio.new_event_loop()가 사용됩니다. 루프는 마지막에 닫힙니다. 이 함수는 asyncio 프로그램의 주요 진입점으로 사용해야 하며, 이상적으로 한 번만 호출되어야 합니다. 이벤트 루프를 구성하려면 loop_factory 를 사용하는 것이 좋습니다.실행기는 종료를 위해 5분이라는 제한 시간이 부여됩니다. 해당 시간 내에 실행이 완료되지 않으면 경고가 발생하고 실행기가 닫힙니다.
예시:
async def main(): await asyncio.sleep(1) print('hello') asyncio.run(main())
Added in version 3.7.
버전 3.9에서 변경:
loop.shutdown_default_executor()를 사용하도록 업데이트되었습니다.버전 3.10에서 변경: debug 은 전역 디버그 모드 설정을 따르도록 기본값이
None입니다.버전 3.12에서 변경: loop_factory 매개변수가 추가되었습니다.
버전 3.14에서 변경: coro 는 어떠한 어웨이터블 객체든 될 수 있습니다.
Runner 컨텍스트 관리자¶
- class asyncio.Runner(*, debug=None, loop_factory=None)¶
동일한 컨텍스트 내에서 여러 개 의 비동기 함수 호출을 간소화하는 컨텍스트 관리자입니다.
때로는 동일한 이벤트 루프 및
contextvars.Context내에서 여러 개의 최상위 비동기 함수를 호출해야 하는 경우가 있습니다.debug 가
True이면 이벤트 루프가 디버그 모드로 실행됩니다.False는 디버그 모드를 명시적으로 비활성화합니다.None은 전역 디버그 모드 설정을 따릅니다.loop_factory 는 루프 생성을 재정의하는 데 사용될 수 있습니다. 생성된 루프를 현재 루프로 설정하는 것은 loop_factory 의 책임입니다. 기본적으로 loop_factory 가
None인 경우asyncio.new_event_loop()이(가) 호출되어 생성된 루프를asyncio.set_event_loop()로 사용하여 현재 이벤트 루프로 설정합니다.기본적으로,
asyncio.run()예제는 다음과 같이 러너를 사용하여 다시 작성할 수 있습니다:async def main(): await asyncio.sleep(1) print('hello') with asyncio.Runner() as runner: runner.run(main())
Added in version 3.11.
- run(coro, *, context=None)¶
내장된 이벤트 루프에서 coro 를 실행합니다.
인자는 모든 어웨이터블(awaitable) 객체일 수 있습니다.
인자가 코루틴이면 Task로 래핑됩니다.
선택적 키워드 전용 context 인자를 통해 코드가 실행될 사용자 정의
contextvars.Context를 지정할 수 있습니다. context 가None이면 러너의 기본 컨텍스트가 사용됩니다.어웨이터블의 결과를 반환하거나 예외를 발생시킵니다.
다른 asyncio 이벤트 루프가 동일한 스레드에서 실행 중일 때 이 함수를 호출할 수 없습니다.
버전 3.14에서 변경: coro 는 어떠한 어웨이터블 객체든 될 수 있습니다.
- close()¶
러너를 닫습니다.
비동기 제너레이터를 파이널리제이션하고, 기본 실행기를 종료하며, 이벤트 루프를 닫고 내장된
contextvars.Context를 해제합니다.
- get_loop()¶
러너 인스턴스와 연관된 이벤트 루프를 반환합니다.
참고
Runner는 지연 초기화 전략을 사용하며, 생성자에서 기초적인 저수준 구조를 초기화하지 않습니다.내장된 loop 및 context 는
with블록에 진입하거나,run()또는get_loop()이(가) 처음 호출될 때 생성됩니다.
키보드 인터럽션 처리¶
Added in version 3.11.
signal.SIGINT\가 Ctrl-C\에 의해 발생하면, 기본적으로 메인 스레드에서 KeyboardInterrupt\ 예외가 발생합니다. 하지만 이것은 asyncio\와 함께 작동하지 않는데, 이는 asyncio 내부를 중단시킬 수 있고 프로그램을 종료하는 것을 지연시킬 수 있기 때문입니다.
이 문제를 완화하기 위해 asyncio 는 다음과 같이 signal.SIGINT 를 처리합니다.
asyncio.Runner.run()은 사용자 코드가 실행되기 전에 커스텀signal.SIGINT처리기를 설치하고, 함수를 벗어날 때 이를 제거합니다.Runner는 전달된 코루틴 실행을 위한 메인 태스크를 생성합니다.Ctrl-C 에 의해
signal.SIGINT가 발생하면, 커스텀 시그널 처리기가asyncio.Task.cancel()을 호출하여 메인 태스크를 취소하며, 이는 메인 태스크 내부에서asyncio.CancelledError를 발생시킵니다. 이 과정에서 파이썬 스택이 풀리고(unwind), 리소스 정리에try/except및try/finally블록을 사용할 수 있습니다. 메인 태스크가 취소된 후,asyncio.Runner.run()은KeyboardInterrupt를 발생시킵니다.사용자가
asyncio.Task.cancel()에 의해 중단될 수 없는 긴밀한 루프를 작성할 수 있으며, 이 경우 이어지는 두 번째 Ctrl-C 는 메인 태스크를 취소하지 않고 즉시KeyboardInterrupt를 발생시킵니다.