1. 并行执行机制
-
子进程级并行:通过
asyncio.create_subprocess_exec
启动的每个外部命令(如python run_spider.py
)会创建一个独立的系统进程,由操作系统直接调度,实现真正的并行执行。 -
协程级并发:主程序通过
asyncio
的事件循环管理这些子进程的启动和输出处理,实现异步非阻塞调度。
2. 任务调度规则
-
初始阶段:根据
asyncio.Semaphore(N)
中N
的设置,最多同时启动N
个子进程。 -
动态填补:每当一个子进程完成(释放一个信号量位置),未执行的任务会立即补上,直到所有任务完成。
-
示例:若设置
Semaphore(3)
,初始启动 3 个子进程;当任意一个子进程结束后,第 4 个任务会立即启动,保持最多 3 个进程并行。
3. 验证示例
以下代码可以直观验证调度行为:
# -*- encoding: utf-8 -*-
"""
@File : async_process_test.py
@Create Time : 2025/05/14 15:18
@Last Modify Time : 2025/05/14 15:18
@Version : v1.0
@Desciption: None
"""
import asyncio
import random
from datetime import datetime
async def demo_task(task_id, semaphore):
async with semaphore:
# 记录进入任务的时间点
start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"{start_time} [Start] Task {task_id}")
# 模拟耗时操作
t1 = random.choice(range(1, 10))
print(f"{start_time} Task {task_id} sleep for {t1} seconds")
await asyncio.sleep(t1)
# 记录任务结束时间点
end_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"{end_time} [End] Task {task_id}")
async def main():
# 显示程序启动时间
print(f"程序启动时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
semaphore = asyncio.Semaphore(3) # 并发数 3
tasks = [demo_task(i, semaphore) for i in range(1, 6)]
await asyncio.gather(*tasks)
# 显示程序结束时间
print(f"程序结束时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
if __name__ == "__main__":
asyncio.run(main())
测试结果:
D:\tool\python3.8.5\python.exe D:\www\pia_download_crawler\xhs_review_report\async_process_test.py
程序启动时间: 2025-05-14 15:22:07
2025-05-14 15:22:07 [Start] Task 1
2025-05-14 15:22:07 Task 1 sleep for 6 seconds
2025-05-14 15:22:07 [Start] Task 2
2025-05-14 15:22:07 Task 2 sleep for 1 seconds
2025-05-14 15:22:07 [Start] Task 3
2025-05-14 15:22:07 Task 3 sleep for 5 seconds
2025-05-14 15:22:08 [End] Task 2
2025-05-14 15:22:08 [Start] Task 4
2025-05-14 15:22:08 Task 4 sleep for 3 seconds
2025-05-14 15:22:11 [End] Task 4
2025-05-14 15:22:11 [Start] Task 5
2025-05-14 15:22:11 Task 5 sleep for 1 seconds
2025-05-14 15:22:12 [End] Task 3
2025-05-14 15:22:12 [End] Task 5
2025-05-14 15:22:13 [End] Task 1
程序结束时间: 2025-05-14 15:22:13
Process finished with exit code 0