Python 코루틴의 구현 방법은 무엇입니까?

WBOY
풀어 주다: 2023-05-20 11:08:14
앞으로
724명이 탐색했습니다.

코루틴이란

Python에서 코루틴은 협업 멀티태스킹을 통해 효율적인 동시 실행을 달성할 수 있는 경량 동시 프로그래밍 방법입니다. 함수 실행을 일시 중단하고 현재 실행 상태를 저장하기 위해 Yield 키워드를 사용하는 것은 코루틴의 특별한 기능입니다. 따라서 코루틴은 특별한 종류의 생성기 함수로 간주될 수 있습니다. 코루틴이 일시 중지되면 send 메서드를 사용하여 실행을 재개할 수 있으며, 재개 시 값이 반환됩니다.

Python 3.4 이전에는 "생성기 코루틴"이라고 불리는 코루틴을 구현하는 데 Yield 키워드가 자주 사용되었습니다. Python 3.4에 asyncio 모듈이 도입된 후에는 async/await 키워드를 사용하여 "네이티브 코루틴"이라는 코루틴 함수를 정의할 수 있습니다.

스레드 및 프로세스와 비교하여 코루틴은 다음과 같은 장점이 있습니다.

  • 경량: 코루틴의 컨텍스트 전환 비용은 매우 적으며 단일 스레드에서 많은 수의 코루틴을 동시에 실행할 수 있습니다.

  • 낮은 대기 시간: 코루틴 실행 중에 스레드 전환이나 잠금 및 잠금 해제에 대한 오버헤드가 없으므로 외부 이벤트에 더 빠르게 응답할 수 있습니다.

  • 효율성: 코루틴 코드는 일반적으로 다중 스레드 및 다중 프로세스 코드보다 더 간결하고 읽기 쉬우며 유지 관리 비용이 더 낮습니다.

코루틴의 사용 시나리오에는 네트워크 프로그래밍, 비동기 I/O, 데이터 흐름 처리, 높은 동시성 작업 등이 포함됩니다.

Generator Coroutine

Python 3에서 Generator Coroutine은 생성기 함수를 사용하여 구현된 코루틴을 의미합니다. 생성기 함수는 생성기 개체를 반환하는 특수 함수입니다. 함수 실행은 항복 문을 통해 일시 중지된 후 다음에 생성기 개체의 "next"() 메서드가 호출될 때 계속됩니다.

다음은 생성기 함수 코루틴과 간단한 비동기 I/O 작업을 포함하는 간단한 생성기 코루틴의 예입니다.

import asyncio

def coroutine():
    print('Coroutine started')
    while True:
        result = yield
        print('Coroutine received:', result)

async def main():
    print('Main started')
    c = coroutine()
    next(c)
    c.send('Hello')
    await asyncio.sleep(1)
    c.send('World')
    print('Main finished')

asyncio.run(main())
로그인 후 복사

결과 출력:

[root@workhost k8s]# python3 test .py
Main 시작됨
코루틴 시작됨
코루틴 수신됨: Hello
코루틴 수신됨: World
Main done

위 코드의 실행 과정을 살펴보겠습니다.

  • 메인 함수가 실행을 시작하고 Main start를 인쇄합니다.

  • 제너레이터 객체 c를 생성하고 next(c)를 호출하여 첫 ​​번째 항복 문에서 실행을 일시 중지합니다.

  • c.send('Hello')를 사용하여 생성기 함수 실행을 재개하고 'Hello'를 생성기 함수의 반환 값으로 사용합니다.

  • 1초 동안 기다리는 동안 주 함수는 실행을 일시 중지하고 이벤트 루프가 다음 작업을 시작할 때까지 기다립니다.

  • 1초 동안 기다린 후 c.send('World')를 사용하여 생성기 함수를 계속 실행하고 'World'를 생성기 함수의 반환 값으로 사용합니다.

  • main 함수는 실행을 재개하고 Main done을 인쇄합니다.

생성기 함수 코루틴을 사용하여 이 코드는 간단한 코루틴을 구현합니다. 생성기 함수는 항복 문을 사용하여 함수 실행을 일시 중지한 다음 send 메서드를 통해 값을 생성기 함수에 전달하여 재개할 수 있습니다. 이러한 방식으로 생성기 함수를 사용하여 비동기 동시성을 달성할 수 있습니다. 예제에 표시된 대로 생성기 함수를 사용하여 비동기 I/O 작업의 결과를 승인하고 인쇄합니다.

네이티브 코루틴

Python 3에서는 새로운 코루틴 유형으로 네이티브 코루틴을 도입했습니다. 네이티브 코루틴은 async/await 키워드를 사용하여 정의되며, 제너레이터 코루틴과 달리 Yield 문 대신 return 문을 사용하여 일반 함수와 같은 값을 반환할 수 있습니다.

다음은 async 키워드로 수정된 코루틴 함수와 간단한 비동기 I/O 작업을 포함하는 간단한 네이티브 코루틴 예입니다.

import asyncio

async def coroutine():
    print('Coroutine started')
    await asyncio.sleep(1)
    print('Coroutine finished')

async def main():
    print('Main started')
    await coroutine()
    print('Main finished')

asyncio.run(main())
로그인 후 복사

결과 출력:

[root@workhost k8s] # python3 test.py
메인 시작됨
코루틴 시작됨
코루틴 완료됨
메인 완료됨

계속해서 실행 프로세스를 살펴보세요.

  • 메인 함수가 실행을 시작하고 메인 시작됨을 인쇄합니다.

  • 코루틴 함수를 호출하고 코루틴 객체로 실행합니다.

  • 코루틴 함수에서 인쇄 코루틴이 시작되었습니다.

  • 코루틴 함수에서 wait asyncio.sleep(1)을 사용하여 함수 실행을 일시 중지하고 1초 동안 기다립니다.

  • 1초 후 코루틴 함수 실행을 재개하고 Coroutine done을 인쇄합니다.

  • main 함수는 실행을 재개하고 Main done을 인쇄합니다.

위 코드에서 네이티브 코루틴 함수 코루틴은 async 키워드를 사용하여 정의되며, 함수 실행을 일시 중지하고 비동기 I/O 작업이 완료될 때까지 기다리는 데 wait 키워드가 사용됩니다. 네이티브 코루틴을 사용하면 동시 비동기 코드를 작성할 수 있으므로 코드 효율성과 성능이 향상됩니다.

两种协程对比

Python 3 中,原生协程和生成器协程是不同的协程实现方式,它们分别具有独特的特点和适用场景。下面,通过对比它们的区别和优缺点,才可以更好地理解它们之间的异同,以便选择适合自己的协程实现方式,从而更好地编写高效、可维护的异步程序。

1.区别:

  • 定义方式不同:原生协程使用 async/await 关键字来定义,而生成器协程使用 yield 关键字来定义。

  • 返回方式不同:原生协程使用 return 语句来返回结果,而生成器协程使用 yield 语句来返回结果。

  • 调用方式不同:原生协程使用 await 关键字来调用,而生成器协程使用 yield from 或 yield 语句来调用。

  • 原生协程与生成器协程的实现方式不同,前者使用 asyncio 库,后者则是 Python 语言内置的特性。

2.优缺点:

原生协程的优点:

  • 代码简洁易懂:使用 async/await 关键字,可以编写出更简洁易懂的协程代码。

  • 性能更高:原生协程不需要创建生成器对象,也不需要通过 yield 语句来控制函数的执行流程,因此能够更加高效地处理异步操作。

  • 支持异步 I/O 和任务处理:原生协程可以支持异步 I/O 操作和并发任务处理,可以在处理异步操作时更加灵活。

原生协程的缺点:

  • 兼容性差:原生协程是 Python 3.5 版本之后才引入的新特性,因此在旧版本的 Python 中无法使用。

  • 异常处理不方便:原生协程在处理异常时比较麻烦,需要使用 try/except 语句来处理。

生成器协程的优点:

  • 兼容性好:生成器协程是 Python 2 和 Python 3 都支持的特性。

  • 可读性好:生成器协程使用 yield 关键字来实现,代码逻辑清晰易懂。

  • 异常处理方便:生成器协程在处理异常时比较方便,可以使用 try/except 语句来处理。

生成器协程的缺点:

  • 性能相对较低:生成器协程需要创建生成器对象,也需要通过 yield 语句来控制函数的执行流程,因此处理异步操作时性能相对较低。

  • 功能有限:生成器协程不能像原生协程一样支持异步 I/O 操作和任务处理。

实战案例

接下来,模拟一个场景,假设实现一个异步的批量处理任务的工具,使用原生协程来实现。

看下面代码:

import asyncio
import random

async def batch_process_task(tasks, batch_size=10):
    # 将任务列表划分为多个批次
    for i in range(0, len(tasks), batch_size):
        batch = tasks[i:i+batch_size]
        # 使用原生协程来异步处理每个批次的任务
        await asyncio.gather(*[process_task(task) for task in batch])

async def process_task(task):
    # 模拟任务处理过程
    await asyncio.sleep(random.uniform(0.5, 2.0))
    print("Task {} processed".format(task))

async def main():
    # 构造任务列表
    tasks = [i for i in range(1, 101)]
    # 并发处理批量任务
    await batch_process_task(tasks, batch_size=10)

if __name__ == '__main__':
    asyncio.run(main())
로그인 후 복사

输出:

[root@workhost k8s]# python3 test.py 
Task 9 processed
Task 10 processed
Task 1 processed
Task 8 processed
Task 6 processed
Task 4 processed
Task 3 processed
Task 2 processed
Task 5 processed
...
...

batch_process_task函数使用原生协程来处理每个批次的任务,而process_task函数则是处理每个任务的函数。在main函数中,任务列表会被构造,并使用batch_process_task函数来异步地处理批量任务。

위 내용은 Python 코루틴의 구현 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:yisu.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿