Python 3.7에 asyncio.run()
이 도입되고 Python 3.10에서 많은 asyncio 함수에서 loop
매개변수가 제거됨에 따라 비동기 라이브러리를 개발하지 않는 한 이벤트 루프를 관리하는 일은 거의 일어나지 않는다. 이벤트 루프 객체는 여전히 존재하며 액세스할 수 있다. 만약 파이썬 3.7 버전 이상에서 작업하고 있다면 asyncio.run()에 대해 감사하면 된다.
asyncio.run(coro)
은 coro
를 실행시키고 결과를 반환할 것이다. 매번 새로운 이벤트 루프를 실행시키며 그 이벤트 루프를 실행 중일 때는 호출 될 수 없다. 이것은 비동기 코드를 실행하는 몇 가지 명백한 방법으로 이어진다.
첫 번째는 모든 것을 비동기 코루틴에 넣고 매우 간단한 엔트리 함수를 가지게 하는 것이다.
import asyncio
async def get_data_from_io():
...
async def process_data(data):
...
async def main():
while true:
data = await get_data_from_io()
await process_data(data)
asyncio.run(main())
두 번째는 각 코루틴 호출을 별도의 run
명령으로 래핑하는 것이다. 이렇게 하면 asyncio의 모든 이점이 손실된다. 그럼에도 이렇게 해야 하는 스크립트가 있을 수도 있다.
import asyncio
async def get_data_from_io():
...
async def process_data(data):
...
def main():
while true:
data = asyncio.run(get_data_from_io())
asyncio.run(process_data(data))
main()
다른 작업이 실행될 수 있도록 이벤트 루프에 제어를 양보하는 간단한 명령은 없다. asyncio 프로그램의 대부분의 경우 이것은 명시적으로 수행하려는 것이 아니라, 특정 유형의 IO를 처리하는 일부 기본 라이브러리에서 반환되는 future
를 기다릴 때 제어가 자동으로 생성되도록 허용하는 것을 선호한다.
그러나 경우에 따라 특히 테스트 및 디버깅 중에 매우 유용하다. 결과적으로 필요에 따라 이를 수행하는 인식된 관용구가 있다.
await asyncio.sleep(0)
위의 코드는 현재 작업을 일시중지시키고 다른 일을 실행할 수 있다. 이 함수는 시간(초)단위의 단일 매개변수를 사용하고 아직 완료로 표시되지 않았지만 지정된 시간(초)가 경과했을 때 표시될 미래를 반환한다.
0초로 지정하면 다른 태스크가 보류 중인 경우 현재 작업을 중단하도록 작동하지만 그렇지 않으면 절전 시간이 0이므로 아무 작업도 수행하지 않는다.
asyncio.sleep
을 0이 아닌 매개변수와 사용할 경우 시간(초)가 경과했을 때 미래가 완료된다고 해서 작업이 항상 그 시간에 다시 깨어나는 것은 아니다. 실제로 이벤트 루프에서 실행 중인 다른 작업이 없을 때만 깨울 수 있기 때문에 그 시간 이후에는 언제든지 다시 깨울 수 있다.
await
, async with
그리고 async for
를 사용할 수 있다.await
를 호출할 때는 반드시 다음 중 하나를 따라야 한다.coroutine
객체future
객체future
를 기다리는 것은 코드를 실행할 수 없지만 다른 프로세스가 완료될 때까지 현재 작업을 일시정지 할수 있다.__await__
를 구현하는 객체future
을 리턴할 수 있다.이것으로 비동기 코드 작성을 위한 기본 구문에 대한 설명을 마칩니다. 이것만으로도 이미 여러 작업을 인스턴스 화하고 교체할 수 있는 좋은 비동기 프로그램을 만들 수 있습니다. 다음 예제는 이 게시물에 포함된 것만 사용하여 작동하는 Python 프로그램입니다.
import asyncio
async def counter(name: str):
for i in range(0, 100):
print(f"{name}: {i!s}")
await asyncio.sleep(0)
async def main():
tasks = []
for n in range(0, 4):
tasks.append(asyncio.create_task(counter(f"task{n}")))
while True:
tasks = [t for t in tasks if not t.done()]
if len(tasks) == 0:
return
await tasks[0]
asyncio.run(main())
이 프로그램은 0에서 99까지의 숫자를 인쇄하는 4개의 작업을 실행하고 각 작업을 인쇄한 후 다른 작업이 인계받을 수 있도록 제어합니다. asyncio
가 여러 작업을 인터리브 처리할 수 있음을 깔끔하게 보여줍니다.