【python】并发编程——协程

Gevent 协程库:Python 中的高效并发编程工具 Gevent 是一个基于 libev 的 Python 协程库,它利用了协程和事件循环来实现高效的并发编程。通过Gevent协程库,我们可以更方便地实现并发编程,并且通过协程间的通信机制,可以实现协程之间的数据交换和协同工作。在 Python 中,Gevent 是一个强大的协程库,它提供了一种简单而高效的方式来实现并发编程。在示例代码中,我们使用了。的简单任务函数,它会在执行过程中暂停 0.5 秒,并打印出任务完成的消息。的简单任务函数,它会在执行过程中暂停0.5秒,并打印出任务完成的消息。 阅读详情

1 一些概念

1.1 协程

执行实体每次执行一个执行流/任务,当前执行流/任务遇阻塞,执行实体切换到其他执行流/任务。执行实体在多个执行流/任务中切换,形成一种并发机制,每个执行流/任务就是一个协程。

1.2 事件循环

直接调用协程返回一个协程对象,并不真正执行协程。协程要在事件循环中被调度执行。事件循环管理协程执行流,当协程阻塞,事件循环将调度其他未阻塞的协程继续执行。
async.run(coro)将启动事件循环并运行主协程coro。await将停止一个阻塞的协程恢复另一个不阻塞的协程。
在这里插入图片描述

2 coroutine in Python

2.1 协程的执行

await coro1()暂停当前协程,切换到协程coro1执行,直到coro1()执行完毕,才恢复main_coro()执行。而对于coro1(),执行到await asyncio.sleep(3),停止执行coro1(),切换执行asyncio.sleep(3)。asyncio.sleep(3)执行耗时3s后,恢复执行coro1(),coro1()执行完毕后切换main_coro执行。这就是切换协程的顺序性。

2.1.1 例子1

import asyncio
import time


async def coro1(x):
    print('coro1 starts!')
    await asyncio.sleep(3)
    print('coro1 ends!')
    return x


async def main_coro():
    print('main_coro starts!')
    ret = await coro1(1)
    print('main_coro1 ends! coro1 return: %d' % ret)


if __name__ == '__main__':
    start_time = time.time()
    asyncio.run(main_coro())
    end_time = time.time()
    print('total cost: %fs' % (end_time - start_time))

'''输出
main_coro starts!
coro1 starts!
coro1 ends!
main_coro1 ends! coro1 return: 1
total cost: 3.002261s
'''

2.1.2 例子2

可以看出这种串行调度并没利用好协程并发处理的优势。可以引入task来应对。

import asyncio
import time


async def fetch_data(data_id: int) -> None:
    print(f'Fetching data for ID {data_id}')
    await asyncio.sleep(3)  # Simulates waiting for a response from a server
    print(f'Finished fetching data for ID {data_id}')


async def main() -> None:
    await fetch_data(1)
    await fetch_data(2)
    await fetch_data(3)


if __name__ == '__main__':
    start_time = time.time()
    asyncio.run(main())
    end_time = time.time()
    print('total cost: %f' % (end_time - start_time))


'''输出
Fetching data for ID 1
Finished fetching data for ID 1
Fetching data for ID 2
Finished fetching data for ID 2
Fetching data for ID 3
Finished fetching data for ID 3
total cost: 9.010200
‘’‘

2.2 协程的并发处理——task

task是对coroutine的封装,以便于并发执行任务。调用asyncio.create_task()将返回一个task对象,同时被封装为task的任务开始进入时间循环执行,而不是要await对应的task对象才执行。例如task1 = asyncio.create_task(fetch_data(1))执行完毕,协程fetch_data(1)就开始在事件循环中被调度运行,而不是执行到await task1的时候才进入事件循环开始执行。

import asyncio
import time


async def fetch_data(data_id: int) -> None:
    print(f'Fetching data for ID {data_id}')
    await asyncio.sleep(3)  # Simulates waiting for a response from a server
    print(f'Finished fetching data for ID {data_id}')


async def main() -> None:
    task1 = asyncio.create_task(fetch_data(1))
    task2 = asyncio.create_task(fetch_data(2))
    task3 = asyncio.create_task(fetch_data(3))

    await task1
    await task2
    await task3


if __name__ == '__main__':
    start_time = time.time()
    asyncio.run(main())
    end_time = time.time()
    print('total cost: %f' % (end_time - start_time))

2.3 主协程

  • 主协程很重要,主协程一定要存活足够长时间,以便其他负载任务的协程能够执行完毕。如果主协程提前退出,则事件循环终止,其他负载工作的协程也终止执行。
  • 主协程main()的最后一行代码是await task1,main()将阻塞直到task1执行完毕然后退出,事件循环终止,尚未执行完的task2和task3将终止执行。如果把await task1换成await asyncio.sleep(4)也可以保证3个任务执行完毕,因为主协程main()驻留4s足够确保3个task(执行时间最长的task3才耗时3s)并发执行完毕。
  • asyncio.run(main())是阻塞执行的,阻塞时间就是主协程main()的生命周期,也是事件循环的生命周期。
    time.sleep(3)在asyncio.run(main())后执行,主线程逗留足够的时间,理论上能够保证剩余2个task都执行完毕,但是剩余两个task都没能完成,因为它们在time.sleep(3)之前就随事件循环终止而被kill了。
import asyncio
import time


async def fetch_data(data_id: int) -> None:
    print(f'Fetching data for ID {data_id}')
    await asyncio.sleep(3)  # Simulates waiting for a response from a server
    print(f'Finished fetching data for ID {data_id}')


async def main() -> None:
    task1 = asyncio.create_task(fetch_data(1))
    task2 = asyncio.create_task(fetch_data(2))
    task3 = asyncio.create_task(fetch_data(3))

    await task1  # 1s后task1执行完毕,主协程也就执行完毕。主协程退出,事件循环终止,尚未执行完毕的task2和task3将终止执行
    # await task2
    # await task3


if __name__ == '__main__':
    start_time = time.time()
    asyncio.run(main())
    time.sleep(3)
    end_time = time.time()
    print('total cost: %f' % (end_time - start_time))


'''输出
Fetching data for ID 1
Fetching data for ID 2
Fetching data for ID 3
Finished fetching data for ID 1
total cost: 4.006973
'''

3 其他话题

3.1 关于事件循环的接口

  • asyncio.get_running_loop():在当前操作系统线程中返回正在运行的事件循环,如果没有正在运行的事件循环,则抛出RuntimeError。
  • asyncio.get_event_loop():如果在协程或者回调函数中调用,则返回当前事件循环。如果当前没有正在运行事件循环,则返回get_event_loop_policy().get_event_loop()的执行结果。在协程或者回调函数中优先使用asyncio.get_runnning_loop(),因为asyncio.get_event_loop()执行比较复杂,尤其是自定义了事件循环策略时。
  • asyncio.set_event_loop(loop):为当前操作系统线程设置当前事件循环
  • asyncio.new_event_loop():创建并返回一个新的事件循环对象

3.2 给事件循环指定执行器(线程/进程)

import asyncio
import concurrent.futures

def blocking_io():
    # File operations (such as logging) can block the
    # event loop: run them in a thread pool.
    with open('/dev/urandom', 'rb') as f:
        return f.read(100)

def cpu_bound():
    # CPU-bound operations will block the event loop:
    # in general it is preferable to run them in a
    # process pool.
    return sum(i * i for i in range(10 ** 7))

async def main():
    loop = asyncio.get_running_loop()

    ## Options:

    # 1. Run in the default loop's executor:
    result = await loop.run_in_executor(
        None, blocking_io)
    print('default thread pool', result)

    # 2. Run in a custom thread pool:
    with concurrent.futures.ThreadPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, blocking_io)
        print('custom thread pool', result)

    # 3. Run in a custom process pool:
    with concurrent.futures.ProcessPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, cpu_bound)
        print('custom process pool', result)

if __name__ == '__main__':
    asyncio.run(main())

4 参考

https://medium.com/python-features/understanding-coroutines-tasks-in-depth-in-python-af2a4c0e1073

最优化问题——一维搜索(一) 最优化问题——一维搜索 1. 一维搜索的引入 1.1 从非线性规划问题到一维搜索 在前面的文章中,我们提到了基于迭代的非线性规划问题的求解思路。在求解过程中,我们提到了在每一步的迭代中都需要对计算步长因子,其计算公式为: λk=minλf(xk+λp)λ_k=min_{λ}f(x_k+λp)λk​=minλ​f(xk​+λp) 我们将f(xk+λp)f(x_k+λp)f(xk​+λp)视为λ的一元函数,我们的目标就是求这个一元函数的极小值。对于这个问题,我通常的求解方式为一维搜索。 1.2 一维搜索的基本形 阅读详情

相关推荐

美团外卖 mtgsig 1.2 逆向工程与补环境实战指南

本文深入解析了美团外卖核心风控参数mtgsig 1.2的生成机制与逆向实战。通过拆解其复杂的JSON结构,揭示了设备指纹、环境信息加密等关键字段。重点阐述了在Node.js中模拟浏览器环境(补环境)的核心方法,包括DOM/BOM对象、本地存储及Canvas/WebGL等高级指纹的模拟技巧,为安全研究和合规自动化测试提供了一套完整的技术指南。

uber9的博客 410

Python实现高并发协程处理

进程:程序在启动后,会在操作系统中作为一个进程存在。不同的进程之间互不影响,各自运行任务。线程:每个进程为了保证多任务运行,会拆分为多个线程,线程共享进程的运行空间;但线程之间要进行切换时,开销比较高,需要保存线程的运行信息以便下次恢复,此时不可避免会影响效率。协程:协程是线程的进一步划分,一个线程中运行多个协程;在线程不进行切换的前提下,使用协程就可以完成并发运算的操作。相对于线程切换实现的并发,协程更加轻量,且效率更高。

pengpengsays 655

翁恺-C语言程序设计 PTA习题集

代码练习题

qq_46085472的博客 7646

Python之并发编程协程

协程介绍,Greenlet,Gevent介绍,Gevent之同步与异步,Gevent之应用举例

weixin_47035302的博客 667

Cube生成定时器2触发双ADC同步采集并用DMA传输

前言 用cube生成一个用定时器触发ADC1,ADC2同步采集的程序,单片机选择的是STM32L476RGT6,用定时器2进行ADC采集触发,更改定时器2的定时周期便可以更改ADC的采样周期,ADC1和ADC2使用同步规则模式,并用DMA进行数据的传输。 STM32的ADC采样完成总共需要的时间是 ADC完成采样时间=采样周期+12个转换周期 举个例子,假如ADC的时钟是15MHz,采样周期是3个周期,3个采样周期加上12个转换周期,一共是15个周期,因为时钟是15MHz,所以完成一次ADC转换总共需要的时

一行代码的博客 4514

【ROS2】手眼标定:moveit2_handeye_calib使用详解

moveit2_handeye_calib MoveIt2 官方的 手眼标定功能包,包含标定插件、图形化界面和示例程序。提供基于 ArUco/ChArUco 标定板的采集与求解功能。标定板下载aruco在线生成器。

郭老二 248

(十六)python之并发编程(协程)

协程

Sean_0819的博客 815

Vibe Writing 手把手教程:Obsidian + Claudian + Skill

本文介绍了Vibe Writing的实操教程,主要使用Obsidian+Claudian+Skill组合。教程包含工具安装配置(Obsidian、Claudian插件)、核心工作流(选题-调研-写作-发布)和效果对比。重点展示了Claude Code生成的文本更具"人味"和场景感,优于其他AI工具。作者强调工具只是辅助,内容灵魂仍需个人思考积累。附有公众号排版和全网发布工具推荐,以及自动配图生成方案。

302

Python之并发编程(协程)

【代码】Python之并发编程(协程)

Mchen的博客 652

精通 Android NDK/JNI:从入门到精通实战与面试精粹

在Android开发中,

郑伟强dev的专栏 144

【测开求职】面试题:数据结构 吐血整理

本篇文章是笔者为准备研究生复试以及校招而写,因此主要针对问答,注重理解,而不在于细节计算。涵盖考研范围内的所有知识内容,读者可以先查看上面的链接走一遍数据结构的整体框架结构。其中,重点难点以及易混淆的知识点,笔者用其他近30篇文章进行了详述,在知识点处贴好了链接,有需要的可以查阅。

vector的博客 7065

Python并发之协程

协程,又称微线程,纤程。英文名Coroutine。协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用。子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。所以子程序调用是通过栈实现的,一个线程就是执行一个子程序。子程序调用总是一个入口,一次返回,调用顺序是明确的。而协程的调用和子程序不同。

上善若泪 4144

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Python并发编程——异步协程

在上篇文章我们学习了,这篇我们学习Python并发编程——异步协程。

霖hero 908

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

118、Python并发编程:一文搞懂协程的概念及Python原生协程的使用

本文通过对多线程、多进程方案中的并发编程的问题的描述,引出了协程的概念,以及协程主要解决的问题。简单比较了进程、线程、协程各自的特点,并描述了Python中协程的实现历程。最后,通过代码演示了基于async/await的原生协程的使用。

南宫理的日知录 1344

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

python协程池_python 并发编程 协程池

协程池from gevent.pool import Poolfrom gevent import monkey;monkey.patch_all()import geventfrom gevent.pool import Poolimport timedef eat(name):print("%s:eat 1" %name)time.sleep(3)print("%s:eat 2" %name...

weixin_39654823的博客 278

【Python】Python并发编程:线程、进程、协程详解

本文介绍了Python中三种并发编程方式:线程(Threading)、进程(Multiprocessing)和协程(Coroutines)。线程适合I/O密集型任务,但受GIL限制;进程能实现真正并行,适合CPU密集型任务;协程通过async/await语法实现高性能异步编程。文章详细对比了三者的优缺点,并提供了基础代码示例,包括线程同步、进程池、进程通信和协程异步请求的实现方法,帮助开发者根据场景选择合适的并发方案。

weixin_42636075的博客 1402

python并发编程中的协程怎么应用

协程(Coroutine)是一种比线程更加轻量级的并发方式,它不需要线程上下文切换的开销,可以在单线程中实现并发。协程通常具有以下特点:协程中的代码可以暂停执行,并且在需要的时候可以恢复执行。多个协程可以在同一线程中并发执行,但是任意时刻只有一个协程在执行。协程通常是基于事件循环(Event Loop)实现的,事件循环负责调度协程的执行。

JttiSEO的博客 259

Python 并发编程(协程)

一、引入 本章节主要介绍,使用单线程实现并发,即只用一个主线程(很明显可利用CPU只有一个),为此我们需要先回顾下并发的本质:切换+保存状态 ps:在介绍进程理论时,提及进程的三种执行状态,而线程才是执行单位,所以也可以将上图理解为线程的三种状态 二、协程介绍 单线程下并发称为:协程 特点: 单线程下的IO等待降到最低,也就是说协程时,遇到IO会切换执行另一个任务,因此将可以将单线程的能力发挥到最大 缺点: 不能实现并行 单线程下的多个任务一旦遇到IO,整个线程都会阻塞,所有任务都停滞 三、Ge

Simple子夜 1308

python并发编程方法_Python并发编程之协程

引入我们知道一个线程同一时间内只能被操作系统分配一个CPU资源, 我们可以基于多进程实现并发, 也可以基于多线程实现并发, CPU正在运行一个任务, 有两种情况下会被切去执行其它任务, 一种是该任务发生了阻塞, 另一是该任务运行时间过长或者被其他优先级更高的任务夺走CPU, 对于单线程来说, 如果一个单线程下运行了多个任务, 那么就不可避免的出现I/O操作, 一旦一个任务出现阻塞的情况, 那么整个...

weixin_34856060的博客 115

Python 并发编程从入门到精通:进程、线程与协程

进程、线程与协程的概念和区别Python 多线程实现及同步机制Python 多进程实现及进程间通信Python 协程并发实现及异步 IO不同并发方式的性能对比和选择策略并发编程的最佳实践和注意事项通过掌握这些知识,可以根据具体需求选择合适的并发模型,开发出高效、稳定的并发程序。并发编程是一个复杂且深入的领域,建议进一步学习异步编程高级技术、分布式系统开发等内容,以应对更复杂的应用场景。

weixin_65516460的博客 844

【Python】并发编程之进程、线程、协程

进程是资源的容器,提供安全隔离,适合独立任务。线程是执行的载体,共享数据但需要同步,适合并发任务。协程是并发的优化,用户态调度,适合高吞吐I/O。(文章实例均为Python语言)

weixin_47520716的博客 708

Python_并发编程(线程,进程,协程)

一条生产线就是一个进程。进程切换需要的资源很最大,效率低线程(Thread):拥有自己独立的栈和共享的堆,共享堆,不共享栈,标准线程由操作系统调度;进程的优缺点进程的优点:1可以使用计算机多核,进行任务的并行执行,提高执行效率2运行不受其他进程影响,创建方便3空间独立,数据安全进程的缺点:进程的创建和删除消耗的系统资源较多进程的创建方式(方法模式)Python的标准库提供了个模块:multiprocessing进程的创建可以通过分为两种方式:1.方法包装2.类包装创建进程后,使用start()启动进程。

2301_80241120的博客 785

Python 并发编程全解析:线程、进程与协程

Python 提供了多种并发编程的方式,每种方式都有其适用场景和优缺点。理解这些技术的原理和应用场景,可以帮助开发者更有效地利用资源,提高程序的性能和响应能力。希望本文能帮助你更好地理解和应用 Python 的并发编程技术。```

2501_91229547的博客 1692

python 并发编程 协程 目录

python 并发编程 协程 协程介绍 python 并发编程 协程 greenlet模块 python 并发编程 协程 gevent模块 python 并发编程 基于gevent模块实现并发的套接字通信 python 并发编程 协程池 python 并发编程 基于gevent模块 协程池 实现并发的套接字通信 转载于:https://www.cnblogs.com/...

weixin_30394251的博客 159

python 协程 await_python教程:使用 async 和 await 协程进行并发编程

python 一直在进行并发编程的优化, 比较熟知的是使用 thread 模块多线程和 multiprocessing 多进程,后来慢慢引入基于 yield 关键字的协程。 而近几个版本,python 对于协程的写法进行了大幅的优化,很多之前的协程写法不被官方推荐了。如果你之前了解过 python 协程,你应该看看最新的用法。并发、并行、同步和异步并发指的是一个 CPU 同时处理多个程序,但是在...

weixin_39546661的博客 159
上一篇: 【python】并发编程——多线程
下一篇: 【python】web应用——WSGI
南隅。
博客等级 码龄8年 279粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值