Python - 비동기 함수가 완료될 때까지 대기

Salman Mehmood 2023년6월21일
  1. await 키워드 사용 및 비동기 함수 만들기
  2. create_task()를 사용하여 작업을 생성하여 문제 해결
Python - 비동기 함수가 완료될 때까지 대기

이 문서에서는 비동기 함수를 만들고 await 키워드를 사용하여 프로세스를 중단하는 방법을 보여줍니다. 또한 ‘파이썬에서 스레드 대신 작업을 사용하는 방법을 배웁니다.

await 키워드 사용 및 비동기 함수 만들기

비동기 프로그래밍은 멀티스레딩이 아닙니다. 다중 처리가 아니라 동시 프로그래밍입니다.

동시성 프로그래밍의 전체 아이디어와 전체 코딩 패턴에 대해 이야기하지는 않지만 기본 원칙과 이를 파이썬에서 구현하는 방법에 대해 이야기할 것입니다.

이제 간단한 예를 살펴보겠습니다. 호출되는 Func_1, Func_2Func_3이 있습니다.

Func_1()
Func_2()
Func_3()

이러한 함수가 비동기적으로 호출되는 경우 Func_1()을 호출한 다음 Func_2()를 호출한다는 의미입니다.

Func_1()이 반환되면 Func_2()만 호출하고 Func_2()가 반환하면 Func_3()을 호출합니다.

다중 스레딩 또는 다중 처리를 사용하면 비동기 프로그래밍과 동일하지 않습니다. 다중 스레딩에서는 이 경우 세 개의 스레드를 정의하고 이 모든 기능을 동시에 실행하기 때문입니다.

또는 거의 동시에 동시에 실행하거나 적어도 동시 실행의 환상을 만들려고 할 것입니다.

그러나 우리는 Func_1()이 생산적인 작업을 수행한 다음 데이터베이스, API에서 일부 데이터를 요청하거나 대기를 위해 일반적으로 잠자고 있다고 가정해 보겠습니다.

그런 일이 발생하면 이 함수가 아직 반환되지 않았더라도 CPU 시간을 낭비하고 Func_2() 실행을 시작하고 싶지 않습니다. 따라서 동시에 하나의 작업만 실행할 수 있습니다. 우리는 다중 처리 또는 다중 스레딩을 수행하지 않습니다.

그러나 Func_1()이 대기 중이거나 대기 중이거나 비생산적인 경우 해당 시간을 활용하여 Func_2()Func_3() 실행을 시작할 수 있습니다. Python에서 비동기 프로그래밍을 수행하려면 asyncio라는 라이브러리를 가져와야 합니다.

전체 프로그램을 비동기식으로 정의하지 않기 때문에 특정 기능은 비동기식입니다. 비동기 함수를 지정하려면 async 키워드를 사용해야 합니다.

Main_Func()만 있으면 전체 프로그램이 비동기화되지만 다음 예제에서는 다른 함수를 추가합니다. 이 함수 내에서 두 개의 print() 함수를 사용합니다.

그리고 그 사이에 우리는 잠을 자게 되지만 time.sleep()으로 잠들지 않을 것입니다. 우리는 asyncio.sleep()을 사용할 것입니다.

asyncio.sleep()을 호출하기 전에 await 키워드를 사용해야 합니다. 즉, 두 번째 인쇄 문이 완료될 때까지 기다립니다. 끝내기 전에 우리는 다른 일을 하지 않을 것입니다.

Main_Func() 함수를 실행하려면 asyncio.run()을 사용해야 하고 run() 함수 내부에서 Main_Func() 함수를 전달해야 합니다. Main_Func() 함수를 호출해야 합니다. 단순히 멀티스레딩이라고 말하는 것이 아닙니다.

import asyncio


async def Main_Func():
    print("Before waiting")
    await asyncio.sleep(1)
    print("After waiting")


asyncio.run(Main_Func())

출력:

비동기 함수가 완료될 때까지 파이썬 대기 - 출력 1

Func_2()라는 또 다른 비동기 함수를 소개하겠습니다. 두 개의 문장을 출력하고 2초 동안 잠들 것입니다.

Main_Func() 함수 내에서 잠자는 대신 await 키워드로 Func_2() 함수를 호출하지만 비동기식은 아닙니다.

import asyncio


async def Main_Func():
    print("Before waiting")
    await Func_2()
    print("After waiting")


async def Func_2():
    print("Func_2: Before waiting")
    await asyncio.sleep(2)
    print("Func_2: After waiting")


asyncio.run(Main_Func())

우리는 함수를 기다리고 있기 때문에 비동기적으로 호출하는 것과 동일하므로 모든 명령이 우리가 정의한 대로 완료될 때까지 이 함수를 실행하지 않습니다.

Before waiting
Func_2: Before waiting
Func_2: After waiting
After waiting

비동기가 아닙니다. 그러나 Main_Func() 함수가 호출될 때 이와 같은 작업을 수행하려면 컨트롤이 Main_Func() 함수의 첫 번째 print 문을 인쇄해야 합니다.

그런 다음 Func_2() 함수를 호출하여 이 함수의 첫 번째 print 문을 인쇄합니다.

이 함수가 잠자고 있는 동안 Main_Func() 함수의 두 번째 print 문을 인쇄해야 하며, 이 작업이 완료되면 Func_2() 함수의 두 번째 print 문을 인쇄해야 합니다.

create_task()를 사용하여 작업을 생성하여 문제 해결

그러기 위해서는 tasks로 작업해야 하므로 Main_Func() 함수 시작 부분에서 asyncio.create_task()를 호출하면서 작업을 생성하고 작업 내부에서 Func_2()를 전달합니다.

유휴 시간이 있으면 해당 작업을 호출한다는 의미입니다.

import asyncio


async def Main_Func():
    Task = asyncio.create_task(Func_2())
    print("Before waiting")
    print("After waiting")


async def Func_2():
    print("Func_2: Before waiting")
    await asyncio.sleep(2)
    print("Func_2: After waiting")


asyncio.run(Main_Func())

코드를 실행한 후 Main_Func() 함수에서 두 개의 print 문이 출력되고 완료된 것을 볼 수 있습니다. 그리고 첫 번째 print 문이 실행되지만 두 번째 print 문을 인쇄하기 전에 실행이 종료됩니다.

Before waiting
After waiting
Func_2: Before waiting

Main_Func()가 주요 기능이기 때문에 컨트롤은 Func_2() 기능을 기다리지 않습니다. 즉, 컨트롤이 Main_Func() 기능의 끝에 도달하면 컨트롤 실행이 중지됩니다. .

컨트롤은 Func_2() 함수의 두 번째 print 문이 완료될 때까지 기다릴 필요가 없으므로 컨트롤이 건너뛸 수 있습니다. 이를 수정하기 위해 Main_Func() 함수 끝에 await Task를 사용합니다.

import asyncio


async def Main_Func():
    Task = asyncio.create_task(Func_2())
    print("Before waiting")
    print("After waiting")
    await Task


async def Func_2():
    print("Func_2: Before waiting")
    await asyncio.sleep(2)
    print("Func_2: After waiting")


asyncio.run(Main_Func())

이제 정의된 대로 인쇄되는 것을 볼 수 있습니다.

Before waiting
After waiting
Func_2: Before waiting
Func_2: After waiting

비동기식으로 작동하는 방식을 보려면 print 문 사이에 sleep() 함수를 사용하면 됩니다.

이는 Main_Func()의 첫 번째 print 문을 실행한 다음 컨트롤이 잠시 휴면 상태가 된다는 것을 의미합니다. 이는 이제 기본 기능에 유휴 시간이 있음을 의미합니다.

이제 Main_Func()가 완전히 실행될 때까지 작업을 실행할 시간이 있습니다. Main_Func() 함수가 잠자기 상태이므로 태스크를 사용하여 호출하여 Func_2() 함수 실행을 시작할 수 있는 CPU 시간이 있음을 의미합니다.

그러나 Func_2() 함수도 휴면 상태가 됩니다. 즉, 이 함수 내에서 컨트롤이 2초 동안 대기하고 컨트롤이 Main_Func() 함수로 이동하여 두 번째 print 문을 인쇄합니다.

그런 다음 제어가 더 이상 Func_2() 함수의 나머지 부분에 관심이 없다는 의미에서 종료됩니다.

async def Main_Func():
    Task = asyncio.create_task(Func_2())
    print("Before waiting")
    await asyncio.sleep(1)
    print("After waiting")

출력:

Before waiting
Func_2: Before waiting
After waiting

관심을 갖고 싶다면 Main_Func() 함수의 끝에서 await Task를 사용해야 합니다.

비동기식입니다. 보시다시피 순서는 Main_Func() 함수가 첫 번째 print 문을 인쇄한 다음 Func_2()가 먼저 인쇄하고 Main_Func()가 두 번째를 인쇄하고 Func_2()를 인쇄하는 것입니다. 두 번째를 인쇄합니다.

함수가 절전 모드로 전환되면 CPU 시간이 낭비되지 않도록 유휴 시간이 사용되기 때문입니다.

비동기 함수가 완료될 때까지 파이썬 대기 - 출력 2

Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn

관련 문장 - Python Async