머리말
이 기사에서는 Python의 다중 코루틴 동시 프로그래밍 (2부) 에 대해 논의할 것입니다 . 내장 기본 라이브러리 asyncio를 사용하여 동시성을 달성하고 먼저 공식을 통해 이 모듈을 사용하십시오. 기본적인 사용법과 인식을 가질 수 있도록 먼저 기초를 잘 다져놓고 다음 글에서 자세히 활용하도록 하겠습니다.
이 글은 파이썬 동시 프로그래밍의 12번째 글입니다.이전 글의 주소는 다음과 같습니다.
Python: 동시 프로그래밍(11)_라이온 킹의 블로그-CSDN 블로그
다음 기사의 주소는 다음과 같습니다.
파이썬: 동시 프로그래밍(13)_Lion King's Blog-CSDN Blog
1. 실전
1. 실시간 채팅 시스템을 시뮬레이션합니다. 각 코루틴은 사용자를 나타내며 사용자는 메시지를 보내고 받을 수 있습니다. 모든 메시지는 콘솔에 인쇄됩니다.
import asyncio
# 定义聊天用户类
class ChatUser:
def __init__(self, name):
self.name = name
async def send_message(self, message):
print(f"{self.name}: Sending message: {message}")
await asyncio.sleep(1) # 模拟发送消息的延迟
async def receive_message(self, message):
print(f"{self.name}: Received message: {message}")
await asyncio.sleep(1) # 模拟接收消息的延迟
# 定义聊天任务
async def chat_task(user):
while True:
message = input(f"{user.name}: Enter message (or 'quit' to exit): ")
if message == "quit":
break
await user.send_message(message)
await user.receive_message(message)
# 创建聊天用户
user1 = ChatUser("User1")
user2 = ChatUser("User2")
# 创建事件循环
loop = asyncio.get_event_loop()
# 运行聊天任务
tasks = [
asyncio.ensure_future(chat_task(user1)),
asyncio.ensure_future(chat_task(user2))
]
loop.run_until_complete(asyncio.wait(tasks))
# 关闭事件循环
loop.close()
위의 코드에서 두 개의 채팅 사용자 개체를 만들고 함수를 사용하여 user1
채팅 작업을 정의했습니다 . 각 채팅 작업은 코루틴을 통해 메시지를 보내고 받는 사용자의 기능을 구현합니다. 메인 루프에서 두 개의 채팅 작업을 실행하고 모든 작업이 완료될 때까지 대기합니다. 마지막으로 이벤트 루프를 닫습니다.user2
chat_task
asyncio.wait()
위의 코드를 실행하면 각 사용자는 콘솔에 메시지를 입력하여 상대방에게 메시지를 보낼 수 있으며, 동시에 상대방이 보낸 메시지를 수신하고 메시지를 콘솔에 출력할 수 있습니다. 이것은 간단한 실시간 채팅 시스템을 시뮬레이트합니다.
2. 주차장에 동시에 진입하고 주차 공간을 놓고 경쟁하는 여러 차량을 시뮬레이션합니다. 각 코루틴은 차량을 나타내며, 주차장 진입 후 임의의 시간 동안 기다린 후 주차장을 떠납니다.
import asyncio
import random
# 定义停车场类
class ParkingLot:
def __init__(self, capacity):
self.capacity = capacity
self.available_spots = capacity
async def enter(self, car):
print(f"Car {car} entering the parking lot.")
if self.available_spots == 0:
print(f"Car {car} is waiting for a spot.")
await asyncio.sleep(1) # 模拟等待时间
await self.enter(car) # 递归调用,继续尝试进入停车场
else:
self.available_spots -= 1
print(f"Car {car} parked. Available spots: {self.available_spots}")
async def exit(self, car):
await asyncio.sleep(random.randint(1, 5)) # 模拟停留时间
self.available_spots += 1
print(f"Car {car} left the parking lot. Available spots: {self.available_spots}")
# 定义车辆任务
async def car_task(car, parking_lot):
await parking_lot.enter(car)
await parking_lot.exit(car)
# 创建停车场对象
parking_lot = ParkingLot(capacity=5)
# 创建事件循环
loop = asyncio.get_event_loop()
# 创建车辆任务
tasks = [
asyncio.ensure_future(car_task(car, parking_lot)) for car in range(10)
]
loop.run_until_complete(asyncio.wait(tasks))
# 关闭事件循环
loop.close()
위의 코드에서는 주차장 객체를 생성 parking_lot
하고 car_task
함수를 사용하여 차량 작업을 정의했습니다. 각 차량은 코루틴을 통해 주차장 출입 기능을 구현한다. 메인 루프에서 우리는 10개의 차량 작업을 생성하고 다음을 사용하여 asyncio.wait()
모든 작업이 완료될 때까지 기다립니다. 각 차량이 주차장에 진입할 때 주차장에 주차 공간이 없을 경우 일정 시간 대기 후 다시 주차장 진입을 시도합니다. 각 차량이 머무르는 시간은 무작위로 주차장에 머무르는 차량의 상황을 시뮬레이션합니다.
위의 코드를 실행하면 여러 대의 차량이 동시에 주차장에 진입하여 주차 공간을 놓고 경쟁하고, 일정 시간 대기 후 주차장을 빠져나가 관련 정보를 동시에 출력할 수 있다. 이는 여러 대의 차량이 동시에 주차장에 진입하는 시나리오를 시뮬레이션합니다.
3. 여러 파일의 내용을 동시에 읽고 읽은 내용을 결과 문자열로 병합
import asyncio
async def read_file(file_name):
print(f"Reading file: {file_name}")
content = ""
try:
with open(file_name, 'r', encoding="utf-8", errors='ignore') as file:
content = file.read()
except FileNotFoundError:
print(f"File not found: {file_name}")
return content
async def read_files(file_names):
tasks = [read_file(file_name) for file_name in file_names]
results = await asyncio.gather(*tasks)
return "".join(results)
# 要读取的文件列表
files = ["file1.txt", "file2.txt", "file3.txt"]
# 创建事件循环
loop = asyncio.get_event_loop()
# 执行并发读取文件任务
result = loop.run_until_complete(read_files(files))
print("Merged content:", result)
# 关闭事件循环
loop.close()
위의 코드에서 read_file
단일 파일의 내용을 읽고 내용을 코루틴으로 반환하는 함수를 정의했습니다. 그런 다음 파일 이름 목록을 가져오고, 여러 코루틴 작업을 만들고, 를 사용하여 모든 작업이 완료될 때까지 대기하고 결과를 문자열로 병합하는 read_files
함수를 정의합니다 .read_file
asyncio.gather
메인 루프에서 이벤트 루프 객체를 생성하고 run_until_complete
run coroutine task 메서드를 사용하여 read_files
파일 목록을 전달합니다. 마지막으로 결합된 콘텐츠 결과를 인쇄합니다.
위의 코드를 실행하면 여러 파일의 내용을 동시에 읽고 하나의 결과 문자열로 결합할 수 있습니다. 이러한 방식으로 파일 읽기 작업을 보다 효율적으로 처리할 수 있으며 프로그램의 실행 속도를 향상시킬 수 있습니다.
2. asyncio 모듈의 주요 기능
1. 용도 async
및 await
키워드
코루틴 함수를 정의할 때 async
키워드를 사용하여 함수를 코루틴 함수로 표시한 다음 await
코루틴 내부에서 키워드를 사용하여 비동기 작업이 완료될 때까지 기다립니다.
2. asyncio.run()
메인 코루틴 실행에 사용
함수를 사용하여 asyncio.run()
기본 코루틴을 실행하고 이벤트 루프를 자동으로 생성 및 종료하여 코드 구조를 단순화할 수 있습니다.
3. asyncio.gather()
여러 코루틴 작업에 대해 동시 대기 사용
asyncio.gather()
함수는 인수로 여러 코루틴 작업을 수신하고 모두 완료될 때까지 기다릴 수 있습니다. 이를 통해 여러 작업을 동시에 실행할 수 있습니다.
4. asyncio.wait()
반복 가능한 객체에서 코루틴 작업을 처리하는 데 사용
asyncio.wait()
함수는 반복 가능한 객체(예: 목록 또는 컬렉션)에서 코루틴 작업을 수신하고 작업이 완료될 때까지 기다립니다. , 등 의 매개변수를 사용하여 return_when
대기 조건을 지정할 수 있습니다.asyncio.FIRST_COMPLETED
asyncio.ALL_COMPLETED
5. asyncio.sleep()
일시정지 시간을 만들기 위해 사용
asyncio.sleep()
함수는 다른 코루틴이 실행될 수 있도록 지정된 시간 동안 이벤트 루프를 일시 중지할 수 있도록 코루틴에 정지 시간을 생성할 수 있습니다.
6. asyncio.TimeoutError
시간 초과 처리에 사용
함수를 사용하여 asyncio.wait_for()
코루틴 작업의 제한 시간을 설정하고 asyncio.TimeoutError
예외를 포착하여 제한 시간 상황을 처리할 수 있습니다.
7. asyncio.Lock()
뮤텍스 구현에 사용
asyncio.Lock()
이 클래스는 상호 배제 잠금 메커니즘을 제공하며 코루틴에서 명령문을 사용하여 async with
잠금을 획득 및 해제하여 하나의 코루틴만 동시에 공유 리소스에 액세스할 수 있도록 할 수 있습니다.
8. asyncio.Queue()
코루틴 간 메시지 전달 구현 에 사용
asyncio.Queue()
클래스는 코루틴 간의 메시징 채널로 사용할 수 있습니다. 코루틴은 메시지를 대기열에 넣을 수 있고 다른 코루틴은 대기열에서 메시지를 가져와 코루틴 간의 비동기 통신을 실현할 수 있습니다.
asyncio.run_coroutine_threadsafe()
9. 멀티스레딩에서 코루틴을 예약하는 데 사용
asyncio.run_coroutine_threadsafe()
함수는 다중 스레드 환경에서 코루틴 작업을 예약하고 실행을 위해 이벤트 루프에 제출할 수 있습니다.
10. asyncio.ensure_future()
코루틴을 래핑하는 데 사용
asyncio.ensure_future()
Task
함수는 이벤트 루프에서 일정 관리 및 관리를 위해 코루틴을 개체로 래핑할 수 있습니다 .