本文目录导读:

在Python异步编程中,保障异步安全主要涉及以下几个方面,我将通过具体案例来说明:
共享状态保护(线程安全 vs 协程安全)
错误案例
import asyncio
# 错误的共享状态
shared_data = [] # 没有保护
async def writer():
for i in range(100):
shared_data.append(i)
await asyncio.sleep(0.01)
async def reader():
while True:
if len(shared_data) > 50:
print(f"数据长度: {len(shared_data)}")
break
await asyncio.sleep(0.01)
async def main():
await asyncio.gather(writer(), reader())
asyncio.run(main())
安全案例(使用锁)
import asyncio
from asyncio import Lock
class SafeSharedData:
def __init__(self):
self._data = []
self._lock = Lock()
async def add(self, item):
async with self._lock:
self._data.append(item)
async def get_length(self):
async with self._lock:
return len(self._data)
async def get_snapshot(self):
async with self._lock:
return self._data.copy()
async def writer(data: SafeSharedData):
for i in range(100):
await data.add(i)
await asyncio.sleep(0.01)
async def reader(data: SafeSharedData):
while True:
length = await data.get_length()
if length > 50:
snapshot = await data.get_snapshot()
print(f"数据长度: {length}")
break
await asyncio.sleep(0.01)
async def main():
data = SafeSharedData()
await asyncio.gather(writer(data), reader(data))
asyncio.run(main())
数据库连接池安全
安全案例
import asyncio
from typing import Optional
from contextlib import asynccontextmanager
class AsyncConnectionPool:
def __init__(self, max_connections=5):
self.max_connections = max_connections
self._connections = []
self._semaphore = asyncio.Semaphore(max_connections)
self._lock = asyncio.Lock()
@asynccontextmanager
async def get_connection(self):
async with self._semaphore:
conn = await self._create_connection()
try:
yield conn
finally:
await self._release_connection(conn)
async def _create_connection(self) -> dict:
# 模拟创建连接
conn = {"id": id(self), "state": "active"}
async with self._lock:
self._connections.append(conn)
return conn
async def _release_connection(self, conn):
async with self._lock:
if conn in self._connections:
self._connections.remove(conn)
conn["state"] = "released"
# 使用示例
async def query_database(pool: AsyncConnectionPool, query_id: int):
async with pool.get_connection() as conn:
# 模拟数据库查询
await asyncio.sleep(0.1)
print(f"查询 {query_id} 完成,连接状态: {conn['state']}")
return f"结果_{query_id}"
async def main():
pool = AsyncConnectionPool(max_connections=3)
tasks = [query_database(pool, i) for i in range(10)]
results = await asyncio.gather(*tasks, return_exceptions=True)
print(f"结果: {results}")
asyncio.run(main())
异步上下文管理器安全
安全案例
import asyncio
from contextlib import asynccontextmanager
class ResourceManager:
def __init__(self):
self._resource = None
self._in_use = False
async def acquire(self):
if self._in_use:
raise RuntimeError("资源已被占用")
self._resource = {"status": "acquired"}
self._in_use = True
return self._resource
async def release(self):
if self._resource:
self._resource["status"] = "released"
self._in_use = False
@asynccontextmanager
async def use_resource(self):
resource = await self.acquire()
try:
yield resource
except Exception as e:
print(f"使用资源时出错: {e}")
raise
finally:
await self.release()
# 安全使用
async def process_data(manager: ResourceManager):
async with manager.use_resource() as resource:
# 处理数据
await asyncio.sleep(0.1)
resource["data"] = "processed"
print(f"资源状态: {resource}")
# 即使在处理中出错,资源也会被释放
# 不安全使用示例(不推荐)
async def unsafe_process(manager: ResourceManager):
# 手动管理资源容易出错
resource = await manager.acquire()
try:
await asyncio.sleep(0.1)
# 可能忘记释放资源
finally:
await manager.release()
异步任务取消安全
import asyncio
from typing import Set
class TaskManager:
def __init__(self):
self._tasks: Set[asyncio.Task] = set()
self._lock = asyncio.Lock()
async def add_task(self, coro):
task = asyncio.create_task(self._safe_run(coro))
self._tasks.add(task)
task.add_done_callback(self._tasks.discard)
return task
async def _safe_run(self, coro):
try:
return await coro
except asyncio.CancelledError:
# 捕获取消信号,进行清理
print("任务被取消,进行清理")
raise
except Exception as e:
print(f"任务出错: {e}")
raise
async def cancel_all(self):
async with self._lock:
for task in self._tasks:
task.cancel()
# 等待所有任务完成取消
await asyncio.gather(*self._tasks, return_exceptions=True)
self._tasks.clear()
@property
def active_count(self):
return len(self._tasks)
# 使用案例
async def long_running_task(task_id: int):
try:
print(f"任务 {task_id} 开始")
await asyncio.sleep(5)
print(f"任务 {task_id} 完成")
return task_id
except asyncio.CancelledError:
print(f"任务 {task_id} 被取消")
raise
async def main():
manager = TaskManager()
# 添加任务
tasks = [manager.add_task(long_running_task(i)) for i in range(3)]
# 等待1秒后取消所有任务
await asyncio.sleep(1)
await manager.cancel_all()
print(f"活动任务数: {manager.active_count}")
asyncio.run(main())
异步文件操作安全
import asyncio
import aiofiles
from pathlib import Path
class SafeFileHandler:
def __init__(self, file_path: str):
self.file_path = Path(file_path)
self._lock = asyncio.Lock()
self._file = None
self._is_open = False
async def __aenter__(self):
await self._open()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
await self._close()
async def _open(self):
if not self._is_open:
self._file = await aiofiles.open(self.file_path, 'a+')
self._is_open = True
async def _close(self):
if self._is_open and self._file:
await self._file.close()
self._is_open = False
self._file = None
async def write_safe(self, content: str):
async with self._lock:
await self._file.write(content + '\n')
await self._file.flush()
async def read_safe(self) -> str:
async with self._lock:
await self._file.seek(0)
return await self._file.read()
# 使用示例
async def log_writer(handler: SafeFileHandler, task_id: int):
for i in range(5):
await handler.write_safe(f"任务 {task_id}: 日志 {i}")
await asyncio.sleep(0.1)
async def main():
async with SafeFileHandler("safe_log.txt") as handler:
tasks = [log_writer(handler, i) for i in range(3)]
await asyncio.gather(*tasks)
# 读取所有内容
content = await handler.read_safe()
print("日志内容:")
print(content)
asyncio.run(main())
关键安全原则总结
- 使用锁机制:对共享状态使用
asyncio.Lock - 使用信号量:控制并发数量用
asyncio.Semaphore - 使用上下文管理器:确保资源正确释放
- 任务取消处理:正确捕获
CancelledError - 避免阻塞操作:使用异步版本的 I/O 操作
- 最小化锁范围:只在必要时加锁
- 处理异常:在任何可能出错的异步操作中处理异常
这些案例展示了如何在Python异步编程中保障执行安全,避免竞态条件和资源泄漏等问题。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播