Python의 일련의 약속

Abdul Mateen 2023년6월21일
  1. Python의 비동기 프로그래밍
  2. 콜백 함수
  3. Python의 시도/제외
  4. Python의 일련의 약속
Python의 일련의 약속

이 튜토리얼은 Python에서 일련의 약속을 작성하는 방법을 알려줍니다. 먼저 Python의 비동기 프로그래밍에 대해 설명합니다.

다음으로 Python의 콜백 함수에 대해 설명합니다. 마지막으로, 실제 주제에 도달하기 전에 Python에서 try/except에 대해 간단히 논의한 다음 Python에서 일련의 약속에 도달합니다.

Python의 비동기 프로그래밍

이 기사에서는 사용자가 운영 체제 스레드에 대한 기본 개념을 알고 있을 것으로 기대합니다. 스레드에 대한 예비 소개가 없으면 운영 체제의 스레드를 전제 조건으로 읽을 수 있습니다.

비동기 프로그래밍을 사용하면 여러 스레드가 병렬로 실행되는 반면 주 프로그램(일반적으로 주/관리자 스레드라고 함)은 여러 작업자 스레드를 만들 수 있습니다. 일반적으로 메인 스레드는 작업 완료 후 메인 스레드에 알리는 작업자 스레드를 기다립니다.

일반 프로그래밍과 달리 경쟁이 끝날 때까지 제어를 유지하는 대신 비동기 함수는 일시 중지하고 다른 함수(스레드)의 병렬 실행을 허용합니다.

우리는 Python에서 비동기 프로그래밍의 예를 논의하고 제공할 것입니다. 그러나 관련 동기 코드를 먼저 확인하는 것이 좋습니다. 이 코드는 비교를 통해 이해를 발전시키는 데 도움이 됩니다.

def count():
    for i in range(5):
        print(i, end=" ")


def main():
    count()
    count()
    count()


main()

여기에서 count 함수를 순서대로 세 번 호출합니다. 출력은 예상대로입니다.

0 1 2 3 4 0 1 2 3 4 0 1 2 3 4

첫 번째 count 함수의 출력, count 함수의 두 번째 호출 출력, 마지막 count 함수의 출력을 볼 수 있습니다.

Python의 asyncio 라이브러리를 사용하면 Python에서 비동기 프로그램을 실행할 수 있습니다. 비동기 프로그래밍의 첫 번째 요구 사항은 함수를 대기 가능한 객체로 설계하는 것입니다.

표준 함수를 어웨이터블 객체로 변환하기 위한 두 가지 요구 사항이 있습니다. 첫 번째는 async 키워드(def 키워드 앞)를 사용하여 루틴 함수 대신 비동기 함수를 만드는 것입니다.

두 번째 요구 사항은 비동기 함수 내에서 sleep 함수를 호출하고 현재 함수를 일시 중단하고 다른 함수를 제어하는 것입니다.

sleep 문은 함수가 정확히 정지 상태로 들어가는 코드의 특정 지점입니다. 비동기 프로그래밍의 두 번째 요구 사항은 대기 가능한 개체(비동기 함수)를 호출하는 동안 await를 추가하는 것입니다. 그렇지 않으면 오류가 발생합니다.

await 키워드는 다른 기능에 실행 시간을 제공하기 위해 현재 기능을 일시 중단하도록 이벤트 루프에 지시합니다.

세 번째 요구 사항은 gather 함수를 호출하고 대기 가능한 개체(비동기 함수)를 전달하는 것입니다. gather 기능은 이러한 기능을 순서대로 동시에 실행합니다.

즉, 첫 번째 기능이 처음에 시작되고 일정 시간이 지나면 두 번째 기능도 병렬로 시작됩니다. 마찬가지로 모든 비동기 함수는 하나씩 동시에 실행되기 시작합니다.

자, 코드를 보자.

import asyncio


async def count():
    for i in range(5):
        print(i, end=" ")
        await asyncio.sleep(0.5)


async def main():
    await asyncio.gather(count(), count(), count())


if __name__ == "__main__":

    asyncio.run(main())

여기서 우리는 이전 코드를 특정 추가 사항이 있는 비동기 코드로 변환했습니다. 첫 번째 줄에서 asyncio 라이브러리를 가져옵니다.

async 키워드는 모든 함수의 시작 부분에 추가됩니다.

수면 기능 호출이 기능에 추가되었습니다. await 키워드는 main 함수를 포함한 모든 함수 호출에 추가됩니다.

마지막으로 gather 함수는 main에서 호출되며 여기서 count 함수는 각 함수 호출을 별도의 스레드로 보여주기 위해 여러 번 호출됩니다.

gather 기능을 사용하여 대기 가능한 개체를 추가하여 동시에 실행할 비동기 기능 그룹을 형성합니다. 이 코드의 출력을 봅시다.

0 0 0 1 1 1 2 2 2 3 3 3 4 4 4

출력에서 모든 스레드가 병렬로 실행되고 함께 실행되는 대신 비동기 출력을 생성하는 것을 볼 수 있습니다.

동일한 함수를 여러 번 호출하는 것과 혼동할 수 있습니다. 다음은 서로 다른 기능이 병렬로 실행되는 또 다른 예입니다.

import asyncio


async def count1():
    for i in range(10):
        print(i, end=" ")
        await asyncio.sleep(0.5)


async def count2():
    for i in range(50, 60):
        print(i, end=" ")
        await asyncio.sleep(0.5)


async def main():
    await asyncio.gather(count1(), count2())


asyncio.run(main())

이 코드의 출력은 다음과 같습니다.

0 50 1 51 2 52 3 53 4 54 5 55 6 56 7 57 8 58 9 59

다시 두 기능이 동시에 실행됩니다.

콜백 함수

콜백이 다른 함수에 전달됩니다(인수로). 다른 함수는 정의의 어딘가에서 이 함수를 콜백해야 합니다.

그러나 호출 지점은 다른 함수가 정의된 방식에 따라 다릅니다.

여기에 콜백 함수와 관련된 간단한 코딩 예제가 있습니다.

import random as r


def callback1(s):
    print(f"******* {s} *******")


def callback2(s):
    print(f"^^^^^^^ {s} ^^^^^^^")


def print_through_callback(message, f1, f2):
    if r.randint(0, 1) == 0:
        f1(message)
    else:
        f2(message)


def main():

    print_through_callback("Callback Example", callback1, callback2)


main()

이 코드에서 print 함수에는 세 개의 매개변수가 있습니다. 두 번째 및 세 번째 매개변수는 일부 함수 이름입니다.

main에서 우리는 두 개의 함수를 전달하고 코드는 임의로 하나를 호출합니다. 이 코드를 여러 번 실행하면 두 함수가 모두 무작위로 호출되는 것을 볼 수 있습니다.

Python의 시도/제외

Python은 예외 처리도 제공합니다. Python에는 코드를 테스트하기 위한 try 블록이 있습니다. 예외 가능성이 있으며 except 블록에서 예외를 처리할 수 있습니다.

우리 모두는 0으로 나누는 것이 정의되지 않았고 프로그램(거의 모든 프로그래밍 언어에서)이 충돌한다는 것을 알고 있습니다. 0으로 나누기 연산을 호출할 때. 잘 모르겠다면 이 코드를 사용해 보세요.

def main():
    x = int(input("Enter any number:"))
    print(2 / x)


main()

0을 입력하고 결과를 확인하십시오. 프로그램이 충돌합니다. 코드 충돌은 나쁜 일이며 예외 처리를 통해 피해야 합니다.

예외 처리와 동일한 코드를 참조하십시오.

def main():
    try:
        x = int(input("Enter any number:"))
        print(2 / x)
    except:
        print("Divide by zero is not defined")


main()

이 코드를 실행하고 0이 아닌 값을 입력해야 합니다. print (2/x) 안에 기록된 나누기 연산의 결과를 얻게 됩니다. 0을 입력하면 프로그램이 충돌 대신 Divide by zero is not defined라는 메시지를 표시합니다.

Python의 일련의 약속

콜백 함수는 일반 함수와 동일합니다. 그러나 용도가 다릅니다.

실행하는 데 많은 시간이 걸리는 무거운 기능을 고려하십시오. 일반적으로 이러한 함수는 비동기화됩니다.

비동기 함수는 백그라운드에서 실행되며 특정 시간이 지나면 완료되지만 다른 함수는 병렬로 시작됩니다. 그러나 어떤 무거운 기능을 완료한 후에 어떤 기능을 실행하고 싶다면 콜백 기능을 사용하는 것이 좋습니다.

그러나 이러한 작업을 완료하는 데 문제가 있습니다. 작업이 완료되기 전에 예외가 발생하면 어떻게 됩니까?

작업을 성공적으로 완료한 후 함수가 호출되도록 하려면 약속 및 비동기 프로그래밍이 필요합니다.

약속

약속은 비동기 함수의 성공 또는 실패(실패) 완료를 나타내는 개체입니다.

Promise 객체는 비동기 함수의 결과 값도 나타냅니다. 약속은 여러 콜백과 관련된 문제를 관리하는 데 사용됩니다.

promise API를 사용하여 Python에서 일련의 약속을 실행할 수 있습니다. 그러나 async/await를 통해 Python에서도 동일한 목적을 달성할 수 있습니다.

비동기 함수를 사용하여 Python에서 구현하려면 비동기 함수와 함께 asyncio 라이브러리를 사용해야 합니다. 이미 위에서 설명한 await 키워드를 사용하여 함수를 순차적으로 호출할 수 있습니다.

마지막으로 try/except 블록을 사용하고 있습니다. 먼저 코드와 출력을 확인하십시오.

나중에 try/except 블록의 목적에 대해 설명하겠습니다.

import asyncio
import random as r


async def f1(x):
    await asyncio.sleep(1)
    return x ** 2


async def f2(x):
    await asyncio.sleep(1)
    return x / 2


async def f3(x):
    if r.randint(0, 1) == 0:
        return x
    raise ValueError(x)


async def run():
    try:
        value = await f3(await f2(await f1(r.randint(5, 9))))
    except ValueError as exception:
        print("Exception Occurred:", exception.args[0])
    else:
        print("No Exception:", value)


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(run())
    loop.close()

다음은 위의 Python 스크립트를 5회 실행한 결과입니다.

No Exception: 12.5
Exception Occurred: 12.5
Exception Occurred: 32.0
No Exception: 18.0
No Exception: 40.5

출력은 일부 비동기 작업에서 성공 또는 실패가 있을 수 있음을 설명합니다. 따라서 try 블록에서 함수 호출 뒤에 콜백 함수에 대한 명령문을 배치할 수 있습니다.

성공적으로 완료되면 코드는 콜백 함수를 실행합니다. 실패 시 컨트롤은 제외 블록으로 이동하고 콜백 기능을 무시합니다.

이런 식으로 파이썬에서 일련의 약속을 처리할 수 있습니다. 성공적으로 완료되면 콜백 함수를 실행합니다(일부 필수 작업의 성공적인 완료에 따라 다름). 그렇지 않으면 콜백 함수를 실행할 필요가 없습니다.