Python异步、同步、并发、并行等概念解析

该文章已生成可运行项目,

往期文章回顾:

Dify DeepResearch 2.0 评测:告别玩具时代?Dify深度研究Agent究竟进化到哪一步了!

飞书“知识问答” 深度实测:一键调用10W+份企业文档,还实时更新,一出手就是降维打击啊!

Dify “Agent节点” 让工作流学会 “自主推理”

36k Star + 2.1k Star!两个热门的MCP开源合集项目介绍,并探索从根上搞懂MCP

5.3k!Dify GitHub热门工作流合集并介绍DIFY+MCP示例

Dify 开源DeepResearch工作流实现本地和Web混合搜索并探索工作流图的正确解析方法(一)

Dify内置DeepResearch工作流溯源——来看看Dify官方博客对它的介绍

Dify内置DeepResearch深度体验,抽丝剥茧带大家瞧瞧它的真实水准

Dify 实现DeepResearch工作流拆解并再看升级版Dify能否搭建出Manus?

深度解析:Dify能否复刻Deep Research与Manus?三大工具深度对比

异步操作的重要性是毋庸置疑的,在LangGraph等框架中大量出现。DIFY玩久了,这些概念有点生疏了,今天来复习一下。

什么是异步操作?

异步操作是一种编程模式,允许程序在等待某些操作完成(如I/O操作)时继续执行其他任务,而不被阻塞。这与传统的同步操作不同,同步操作会使程序在一个操作完成前停止执行任何其他代码。

异步操作的核心概念

1. 非阻塞执行

在异步编程中,当程序遇到可能需要等待的操作时(如网络请求、文件读写),它不会停下来等待结果,而是继续执行其他可以立即处理的任务。

2. 事件循环(Event Loop)

事件循环是异步编程的核心机制,它负责:

  • 调度和执行异步任务
  • 处理完成的任务结果
  • 管理I/O操作的通知
3. 协程(Coroutines)

协程(可以协同的程序?)是可以在执行过程中暂停和恢复函数。在Python中,使用async def定义协程函数,使用await暂停协程执行直到等待的操作完成。

# Apply to workflow.py

async def fetch_data():

    # 发起网络请求

    response = await some_api_call()

    # 当网络请求完成后,继续执行

    return response

4. 任务(Tasks)

任务是对协程的封装,代表一个正执行的操作。可以创建多个任务并并发(异步并发,非并行)执行它们。

# Apply to workflow.py

task1 = asyncio.create_task(fetch_data())

task2 = asyncio.create_task(process_data())

await asyncio.gather(task1, task2)  # 并发执行两个任务

Python中的异步实现

Python通过asyncio库提供异步编程支持:

基本异步程序结构

# Apply to workflow.py

import asyncio

async def main():

    print("开始")

    await asyncio.sleep(1)  # 非阻塞等待1秒

    print("1秒后")

asyncio.run(main())  # 运行异步程序

并发执行多个任务

async def main():

    # 创建三个并发任务

    task1 = asyncio.create_task(some_coroutine())

    task2 = asyncio.create_task(another_coroutine())

    task3 = asyncio.create_task(third_coroutine())

    

    # 等待所有任务完成

    results = await asyncio.gather(task1, task2, task3)

    return results

注意:这里的并发并不是在多个CPU核心上同时执行,而是在单个CPU线程内通过事件循环交替执行多个任务。

异步操作的优势

  • 提高程序效率:在等待I/O操作时可以执行其他任务,提高CPU利用率
  • 提升响应性:特别是在网络应用和UI程序中,可以保持界面响应
  • 处理大量并发连接:适合需要同时处理多个连接的服务器应用
  • 资源利用优化:单线程中实现并发,避免了线程切换的开销

异步操作的应用场景

  • 网络应用:处理多个HTTP请求、WebSocket连接
  • 数据库操作:并发执行多个查询
  • 文件操作:同时读写多个文件
  • API调用:并行调用多个外部服务
  • AI模型调用:同时处理多个模型推理请求

在AI应用中的异步操作

在AI和大语言模型应用中,异步操作尤为重要:

  • 模型调用:LLM API调用通常有较长延迟,异步可以同时处理多个请求
  • 工具使用:AI代理使用多个工具时可以并行执行
  • 流式响应处理:处理模型的流式输出
  • 多代理系统:让多个AI代理并行工作

异步与并行的区别

  • 异步:在单线程中通过事件循环交替执行多个任务
  • 并行:在多个CPU核心上同时执行多个任务(注意并行和并发的区别

异步主要解决的是I/O等待问题,而非计算密集型问题。对于计算密集型任务,多进程并行可能更合适。

同步与异步操作对比详解

基本概念

同步操作:按顺序执行任务,一个任务完成后才开始下一个任务,期间程序会被阻塞。

异步操作:允许多个任务交替执行,当一个任务在等待(如I/O操作)时,可以执行其他任务,提高整体效率。

通过实例对比

场景一:网络请求

假设我们需要从三个不同的API获取数据:

同步方式
import requests

import time

def get_data_sync():

    start_time = time.time()

    
    # 依次发送三个请求

    response1 = requests.get('https://api.example.com/data1')  # 等待1秒

    print(f"获取数据1完成,用时:{time.time() - start_time:.2f}秒")


    response2 = requests.get('https://api.example.com/data2')  # 等待1秒

    print(f"获取数据2完成,用时:{time.time() - start_time:.2f}秒")


    response3 = requests.get('https://api.example.com/data3')  # 等待1秒

    print(f"获取数据3完成,用时:{time.time() - start_time:.2f}秒")

    
    return [response1.json(), response2.json(), response3.json()]

# 执行同步请求

results = get_data_sync()

输出:

获取数据1完成,用时:1.05秒
获取数据2完成,用时:2.10秒
获取数据3完成,用时:3.15秒

异步方式

import asyncio
import aiohttp
import time

async def get_data_async():
    start_time = time.time()
    async with aiohttp.ClientSession() as session:
        # 创建三个并发请求任务
        task1 = asyncio.create_task(
            session.get('https://api.example.com/data1'))

        task2 = asyncio.create_task(
            session.get('https://api.example.com/data2'))

        task3 = asyncio.create_task(
            session.get('https://api.example.com/data3'))

        # 等待所有请求完成
        response1 = await task1
        print(f"获取数据1完成,用时:{time.time() - start_time:.2f}秒")

        response2 = await task2
        print(f"获取数据2完成,用时:{time.time() - start_time:.2f}秒")

        response3 = await task3
        print(f"获取数据3完成,用时:{time.time() - start_time:.2f}秒")

        # 解析JSON响应
        data1 = await response1.json()
        data2 = await response2.json()
        data3 = await response3.json()

        return [data1, data2, data3]

# 执行异步请求

results = asyncio.run(get_data_async())

输出:

获取数据1完成,用时:1.02秒
获取数据2完成,用时:1.03秒
获取数据3完成,用时:1.05秒

场景二:文件读写

同步方式
import time

def read_files_sync():
    start_time = time.time()
    
    with open('file1.txt', 'r') as f:
        content1 = f.read()  # 可能需要0.5秒
    print(f"读取文件1完成,用时:{time.time() - start_time:.2f}秒")
    
    with open('file2.txt', 'r') as f:
        content2 = f.read()  # 可能需要0.5秒
    print(f"读取文件2完成,用时:{time.time() - start_time:.2f}秒")
    
    with open('file3.txt', 'r') as f:
        content3 = f.read()  # 可能需要0.5秒
    print(f"读取文件3完成,用时:{time.time() - start_time:.2f}秒")
    
    return [content1, content2, content3]

# 执行同步读取
contents = read_files_sync()

输出:

读取文件1完成,用时:0.50秒
读取文件2完成,用时:1.00秒
读取文件3完成,用时:1.50秒

异步方式
import asyncio
import time

async def read_file(filename):
    # 使用异步文件IO
    async with asyncio.open_file(filename, 'r') as f:
        return await f.read()

async def read_files_async():
    start_time = time.time()
    
    # 创建三个并发读取任务
    task1 = asyncio.create_task(read_file('file1.txt'))
    task2 = asyncio.create_task(read_file('file2.txt'))
    task3 = asyncio.create_task(read_file('file3.txt'))
    
    # 等待所有任务完成
    content1 = await task1
    print(f"读取文件1完成,用时:{time.time() - start_time:.2f}秒")
    
    content2 = await task2
    print(f"读取文件2完成,用时:{time.time() - start_time:.2f}秒")
    
    content3 = await task3
    print(f"读取文件3完成,用时:{time.time() - start_time:.2f}秒")
    
    return [content1, content2, content3]

# 执行异步读取
contents = asyncio.run(read_files_async())

输出:

读取文件1完成,用时:0.51秒
读取文件2完成,用时:0.52秒
读取文件3完成,用时:0.53秒

场景三:AI模型调用

同步方式
from langchain_openai import ChatOpenAI
import time

def process_queries_sync():
    start_time = time.time()
    model = ChatOpenAI(model="gpt-3.5-turbo")
    
    # 依次处理三个查询
    response1 = model.invoke("解释什么是人工智能")
    print(f"查询1完成,用时:{time.time() - start_time:.2f}秒")
    
    response2 = model.invoke("解释什么是机器学习")
    print(f"查询2完成,用时:{time.time() - start_time:.2f}秒")
    
    response3 = model.invoke("解释什么是深度学习")
    print(f"查询3完成,用时:{time.time() - start_time:.2f}秒")
    
    return [response1, response2, response3]

# 执行同步查询
results = process_queries_sync()

输出:

查询1完成,用时:2.50秒
查询2完成,用时:5.00秒
查询3完成,用时:7.50秒

异步方式

import asyncio
from langchain_openai import ChatOpenAI
import time

async def process_queries_async():
    start_time = time.time()
    model = ChatOpenAI(model="gpt-3.5-turbo")
    
    # 创建三个并发查询任务
    task1 = asyncio.create_task(model.ainvoke("解释什么是人工智能"))
    task2 = asyncio.create_task(model.ainvoke("解释什么是机器学习"))
    task3 = asyncio.create_task(model.ainvoke("解释什么是深度学习"))
    
    # 等待所有任务完成
    response1 = await task1
    print(f"查询1完成,用时:{time.time() - start_time:.2f}秒")
    
    response2 = await task2
    print(f"查询2完成,用时:{time.time() - start_time:.2f}秒")
    
    response3 = await task3
    print(f"查询3完成,用时:{time.time() - start_time:.2f}秒")
    
    return [response1, response2, response3]

# 执行异步查询
results = asyncio.run(process_queries_async())

输出:

查询1完成,用时:2.55秒
查询2完成,用时:2.60秒
查询3完成,用时:2.65秒

何时使用异步?

异步操作特别适合以下场景:

  • 高I/O负载:大量网络请求、文件操作
  • 用户交互:需要保持界面响应
  • 服务器应用:处理大量并发连接
  • API集成:调用多个外部服务
  • AI应用:并行处理多个模型调用或工具使用

何时使用同步?

同步操作适合以下场景:

  • 简单脚本:执行简单的顺序任务
  • CPU密集型计算:纯计算任务不会从异步中获益
  • 依赖严格顺序:任务之间有严格的顺序依赖
  • 代码清晰度优先:需要保持代码简单易读

Python异步并发与CPU执行解析

Python异步的工作原理

单线程事件循环模型

Python的asyncio使用的是单线程事件循环模型:

  • 所有任务都在同一个线程中运行
  • 事件循环负责在不同任务之间切换执行
  • 当一个任务遇到await语句时,它会暂时让出控制权
  • 事件循环会转而执行其他准备好的任务

异步并发与多处理器并行的区别

异步并发(Asynchronous Concurrency)
  • 在单个CPU线程上运行
  • 适合I/O密集型任务(如网络请求、文件读写)
  • 通过事件循环在等待I/O时切换任务
  • 使用asyncio、async/await实现
多处理器并行(Multiprocessing Parallelism)
  • 在多个CPU核心上同时运行
  • 适合CPU密集型任务(如大量计算)
  • 真正的同时执行
  • 使用multiprocessing模块实现

实际例子对比

异步并发(单CPU线程)
import asyncio
import time

async def io_task(name, delay):
    print(f"{name} 开始于 {time.strftime('%X')}")
    await asyncio.sleep(delay)  # 模拟I/O操作(如网络请求)
    print(f"{name} 完成于 {time.strftime('%X')}")
    return f"{name} 结果"

async def main():
    # 这些任务在同一个CPU线程中并发执行
    tasks = [
        asyncio.create_task(io_task("任务A", 2)),
        asyncio.create_task(io_task("任务B", 1)),
        asyncio.create_task(io_task("任务C", 3))
    ]
    results = await asyncio.gather(*tasks)
    return results

# 运行异步程序
results = asyncio.run(main())
print(results)

输出:

任务A 开始于 10:00:00
任务B 开始于 10:00:00
任务C 开始于 10:00:00
任务B 完成于 10:00:01
任务A 完成于 10:00:02
任务C 完成于 10:00:03
['任务A 结果', '任务B 结果', '任务C 结果']

多处理器并行(多CPU核心)

import multiprocessing
import time

def cpu_task(name, seconds):
    print(f"{name} 开始于 {time.strftime('%X')}")
    # 执行CPU密集型计算
    start = time.time()
    while time.time() - start < seconds:
        pass  # 纯CPU计算
    print(f"{name} 完成于 {time.strftime('%X')}")
    return f"{name} 结果"

if __name__ == "__main__":
    # 这些进程在不同CPU核心上并行执行
    with multiprocessing.Pool(processes=3) as pool:
        tasks = [
            pool.apply_async(cpu_task, ("进程A", 2)),
            pool.apply_async(cpu_task, ("进程B", 1)),
            pool.apply_async(cpu_task, ("进程C", 3))
        ]
        results = [task.get() for task in tasks]
    
    print(results)

输出:

进程A 开始于 10:00:00
进程B 开始于 10:00:00
进程C 开始于 10:00:00
进程B 完成于 10:00:01
进程A 完成于 10:00:02
进程C 完成于 10:00:03
['进程A 结果', '进程B 结果', '进程C 结果']
何时选择异步并发

异步并发(如你代码中的示例)最适合:

  • I/O密集型任务:网络请求、API调用、数据库查询、文件操作
  • 大量并发连接:Web服务器处理多个客户端连接
  • 需要保持响应性:GUI应用、Web应用
  • 资源受限环境:线程开销太大的场景
何时选择多处理器并行

多处理器并行最适合:

  • CPU密集型任务:数据处理、图像处理、数学计算
  • 可以分割的独立任务:批处理作业、并行算法
  • 需要绕过GIL限制:Python的全局解释器锁限制了线程的真正并行
  • 充分利用多核心CPU:在多核系统上提高性能

总结

异步操作是现代编程中处理并发的重要技术,特别适合I/O密集型应用。在Python中,通过asyncio库和async/await语法可以轻松实现异步编程。在AI应用开发中,异步操作能够显著提高系统吞吐量和响应速度,是构建高效AI系统的关键技术之一。

本文章已经生成可运行项目
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值