本文将和大家一起探讨python的多协程并发编程(下篇),使用内置基本库asyncio来实现并发,先通过官方来简单使用这个模块。先打好基础,能够有个基本的用法与认知,后续文章,我们再进行详细使用。
本文为python并发编程的第十二篇,上一篇文章地址如下:
python:并发编程(十一)_Lion King的博客-CSDN博客
下一篇文章地址如下:
python:并发编程(十三)_Lion King的博客-CSDN博客
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()
等待所有任务完成。最后,我们关闭了事件循环。
通过运行以上代码,每个用户可以在控制台上输入消息,并将消息发送给对方,同时也能接收对方发送的消息,并将消息打印到控制台上。这样模拟了一个简单的实时聊天系统。
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()
等待所有任务完成。每个车辆进入停车场时,如果停车场没有可用车位,则等待一段时间后再次尝试进入停车场,直到成功进入为止。每个车辆停留的时间是随机的,模拟了车辆在停车场停留的情况。
通过运行以上代码,多个车辆可以同时进入停车场并争夺车位,等待一段时间后离开停车场,同时打印出相关信息。这样模拟了多车辆同时进入停车场的情景。
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
方法运行read_files
协程任务,并将文件列表传递给它。最后,我们打印合并后的内容结果。
通过运行以上代码,可以并发地读取多个文件的内容,并将内容合并到一个结果字符串中。这样可以更高效地处理文件读取操作,提高程序的执行速度。
async
和await
关键字在定义协程函数时,使用async
关键字标记函数为协程函数,然后在协程内部使用await
关键字来等待异步操作的完成。
asyncio.run()
来运行主协程可以使用asyncio.run()
函数来运行主协程,并自动创建和关闭事件循环,简化代码结构。
asyncio.gather()
同时等待多个协程任务asyncio.gather()
函数可以接收多个协程任务作为参数,并等待它们全部完成。这样可以实现并发执行多个任务。
asyncio.wait()
来处理可迭代对象中的协程任务asyncio.wait()
函数接收一个可迭代对象(如列表或集合)中的协程任务,并等待它们中的任何一个完成。可以使用return_when
参数指定等待条件,如asyncio.FIRST_COMPLETED
、asyncio.ALL_COMPLETED
等。
asyncio.sleep()
来创建暂停时间asyncio.sleep()
函数可以在协程中创建一个暂停时间,让事件循环暂停一段指定的时间,以便其他协程有机会执行。
asyncio.TimeoutError
来处理超时可以使用asyncio.wait_for()
函数来设置协程任务的超时时间,并捕获asyncio.TimeoutError
异常来处理超时情况。
asyncio.Lock()
实现互斥锁asyncio.Lock()
类提供了互斥锁的机制,可以在协程中使用async with
语句来获取和释放锁,确保同一时间只有一个协程可以访问共享资源。
asyncio.Queue()
实现协程间的消息传递asyncio.Queue()
类可以用作协程之间的消息传递通道。一个协程可以将消息放入队列,而另一个协程可以从队列中获取消息,实现协程间的异步通信。
asyncio.run_coroutine_threadsafe()
在多线程中调度协程asyncio.run_coroutine_threadsafe()
函数可以在多线程环境中调度协程任务,并将其提交给事件循环进行执行。
asyncio.ensure_future()
来包装协程asyncio.ensure_future()
函数可以将协程包装为Task
对象,以便在事件循环中进行调度和管理。