1.Python:并发编程之Future
2.å¨Pythonä¸ä½¿ç¨Asyncioç³»ç»ï¼3-4ï¼Task å Future
3.python2.7.12中如何引用模块做整数相除
4.从c++20协程的源码使用彻底搞懂协程的本质
Python:并发编程之Future
学习并发编程时,首先得区分并发与并行。并发(concurrency)对应的源码是 Python 中的多线程或协程,意味着在同一时刻只能运行一个线程或协程,源码通过不断地切换实现并发处理,源码适用于 I/O 频繁的源码操作。并行(parallelism)则对应多进程,源码燕窝国标朔源码在多个 CPU 上同时运行,源码适用于 CPU 密集型的源码操作。
线程在 Python 中由操作系统底层提供,源码它能跟踪每个线程的源码信息,并在适当的源码时候自动进行线程切换,无需我们手动调度。源码然而,源码这也容易引发 race condition。源码interest截图宝源码引入线程概念的源码原因在于,单线程程序往往效率低下,多线程版本则能显著提升速度。
对比单线程与多线程,单线程程序按照顺序执行,每一步都需要等待 I/O 操作完成,因此整体速度较慢。而多线程版本通过创建线程池,利用 ThreadPoolExecutor 类,设置最大线程数,如 max_workers 参数,可实现并行处理,显著提高下载速度。中标溯源码燕窝
在多线程代码中,map 方法被用于并发调用函数,类似普通的内置 map 函数,但效率更高。requests.get 函数线程安全,因此在多线程环境下,它不会引发 race condition。然而,线程切换由操作系统负责,可能会导致结果乱序。
Future 是并发编程的关键概念,是 concurrent.futures 模块和 asyncio 模块的重要组成部分。Future 类代表一个尚未完成或已完成的up博客源码延迟计算任务,类似于 JavaScript 中的 Promise 对象。通常情况下,不应直接创建 Future 实例,而是通过并发框架(如 concurrent.futures 和 asyncio)来生成实例,因为 Future 表示即将发生的事情,其执行时间已经排定。
生成 Future 实例的方法是通过 Executor 子类为需要排定的某件事安排执行。了解 Executor.submit 方法用于接收一个可调用对象,并为其安排执行,返回一个 Future 实例。Executor.map 方法则用于并行处理一系列任务,返回一个迭代器,迭代器的新纪元街机源码 __next__ 方法会调用各个 Future 实例的结果。
Future 实例具有状态,可以是 running、pending 或 finished。Future.done() 方法用于立即返回布尔值,表示 Future 是否已完成。Future.add_done_callback 方法允许在 Future 运行结束后调用一个可调用对象。Future.result 方法用于获取 Future 的结果,如果在执行结束时调用,则返回可调用对象的结果或异常。如果 Future 还未完成,且 timeout 参数被指定,调用 Future.result() 方法会阻塞调用方所在的线程,直到有结果返回,或抛出 TimeoutError 异常。
concurrent.futures.as_completed 是一个迭代器,接收 Future 列表,返回在 Future 运行结束后产出的 Future。通过 Executor.submit 创建 Future,使用 as_completed 进行管理,可实现更精细的并发控制。
å¨Pythonä¸ä½¿ç¨Asyncioç³»ç»ï¼3-4ï¼Task å Future
Task å Futureåé¢æ们讨论äºåç¨ï¼ä»¥åå¦ä½å¨å¾ªç¯ä¸è¿è¡å®ä»¬ææç¨ãç°å¨ææ³ç®åè°è°TaskåFuture apiãä½ å°ä½¿ç¨æå¤çæ¯Taskï¼å ä¸ºä½ ç大é¨åå·¥ä½å°æ¶å使ç¨create_task()å½æ°è¿è¡åç¨ï¼å°±åå¨ç¬¬é¡µçâå¿«éå¼å§âä¸è®¾ç½®çé£æ ·ãFutureç±»å®é ä¸æ¯Taskçè¶ ç±»ï¼å®æä¾äºä¸å¾ªç¯äº¤äºæä½çææåè½ã
å¯ä»¥è¿æ ·ç®åå°ç解:Future表示æ个活å¨çæªæ¥å®æç¶æï¼å¹¶ç±å¾ªç¯ç®¡çãTaskæ¯å®å ¨ç¸åçï¼ä½æ¯å ·ä½çâactivityâæ¯ä¸ä¸ªåç¨ââå¯è½æ¯ä½ ç¨async defå½æ°å ä¸create_task()å建çåç¨ã
Future类表示ä¸å¾ªç¯äº¤äºçæ个ä¸è¥¿çç¶æãè¿ä¸ªæ述太模ç³äºï¼ä¸å¤ªæç¨ï¼æä»¥ä½ å¯ä»¥å°Futureå®ä¾è§ä¸ºä¸ä¸ªåæ¢å¨ï¼ä¸ä¸ªå®æç¶æçåæ¢å¨ãå½å建Futureå®ä¾æ¶ï¼åæ¢è®¾ç½®ä¸ºâå°æªå®æâç¶æï¼ä½ç¨åå®å°æ¯âå®æâç¶æãäºå®ä¸ï¼Futureå®ä¾æä¸ä¸ªå为done()çæ¹æ³ï¼å®å è®¸ä½ æ£æ¥ç¶æï¼å¦ç¤ºä¾ 3-æ示ã
ç¤ºä¾ 3-. ç¨done()æ¹æ³æ£æ¥å®æç¶æ
Futureå®ä¾è¿å¯ä»¥æ§è¡ä»¥ä¸æä½ï¼
• 设置ä¸ä¸ªresultå¼ï¼ç¨.set_result(value)设置å¼å¹¶ä¸ä½¿ç¨ .result()è·åå¼ï¼
• 使ç¨.cancel()æ¹æ³åæ¶ (并ä¸ä¼ç¨ä½¿ç¨.cancelled()æ£æ¥æ¯å¦åæ¶)
• å¢å ä¸ä¸ªFutureå®ææ¶åè°çå½æ°
å³ä½¿Taskæ´å¸¸è§ï¼ä¹ä¸å¯è½å®å ¨é¿å 使ç¨Futureï¼ä¾å¦ï¼å¨æ§è¡å¨ä¸è¿è¡å½æ°å°è¿åFutureå®ä¾ï¼èä¸æ¯Taskã让æ们快éçä¸ä¸ ç¤ºä¾ 3- ï¼äºè§£ä¸ä¸ç´æ¥ä½¿ç¨Futureå®ä¾æ¯ä»ä¹æè§ã
ç¤ºä¾ 3-. ä¸Futureå®ä¾ç交äº
ï¼L3ï¼å建ä¸ä¸ªç®åç mainå½æ°ãæ们è¿è¡è¿ä¸ªå½æ°ï¼çä¸ä¸ä¼å¿ç¶åå¨Future fä¸è®¾ç½®ä¸ä¸ªç»æã
ï¼L5ï¼è®¾ç½®ä¸ä¸ªç»æã
ï¼L8ï¼æå¨å建ä¸ä¸ªFutureå®ä¾ã注æï¼è¿ä¸ªå®ä¾(é»è®¤æ åµä¸)ç»å®å°æ们ç循ç¯ï¼ä½å®æ²¡æä¹ä¸ä¼è¢«éå å°ä»»ä½åç¨(è¿å°±æ¯Tasksçä½ç¨)ã
ï¼L9ï¼å¨åä»»ä½äºæ ä¹åï¼ç¡®è®¤futureè¿æ²¡æå®æã
ï¼Lï¼å®æmain()åç¨ï¼ä¼ éfutureã请记ä½ï¼main()åç¨æåçææå·¥ä½å°±æ¯sleepï¼ç¶ååæ¢Futureå®ä¾ã(注æmain()åç¨è¿ä¸ä¼å¼å§è¿è¡ï¼åç¨åªå¨äºä»¶å¾ªç¯è¿è¡æ¶æå¼å§è¿è¡ã)
(L)å¨è¿éæ们å¨Futureå®ä¾ä¸èä¸æ¯Taskå®ä¾ä¸ä½¿ç¨run_until_complete()ãè¿åä½ ä»¥åè§è¿çä¸ä¸æ ·ãç°å¨å¾ªç¯æ£å¨è¿è¡ï¼main()åç¨å°å¼å§æ§è¡.
ï¼Lï¼æç»ï¼å½futureçç»æ被设置æ¶ï¼å®å°±å®æäºãå®æåï¼å¯ä»¥è®¿é®ç»æã
å½ç¶ï¼ä½ ä¸å¤ªå¯è½ä»¥è¿éæ示çæ¹å¼ç´æ¥ä½¿ç¨Futureï¼ä»£ç 示ä¾ä» ç¨äºæè²ç®çãä½ ä¸asynccioç大é¨åèç³»é½æ¯éè¿Taskå®ä¾è¿è¡çã
ä½ å¯è½æ³ç¥éå¦æå¨Taskå®ä¾ä¸è°ç¨set_result()ä¼åçä»ä¹ãå¨Python 3.8ä¹åå¯ä»¥è¿æ ·åï¼ä½ç°å¨ä¸å 许è¿ä¹åäºãä»»å¡å®ä¾æ¯åç¨å¯¹è±¡çå è£ å¨ï¼å®ä»¬çç»æå¼åªè½å¨å é¨è®¾ç½®ä¸ºåºå±åç¨å½æ°çç»æï¼å¦ ç¤ºä¾ 3-æ示é£æ ·ã
ç¤ºä¾ 3-. å¨taskä¸è°ç¨set_result
ï¼Lï¼å¯ä¸çåºå«æ¯æ们å建çæ¯Taskå®ä¾èä¸æ¯Futureå®ä¾ãå½ç¶ï¼Task APIè¦æ±æ们æä¾ä¸ä¸ªåç¨ï¼è¿éæ们使ç¨sleep()åªæ¯å 为ç®åæ¹ä¾¿ã
ï¼L7ï¼æ£å¨ä¼ å ¥ä¸ä¸ªTaskå®ä¾ãå®æ»¡è¶³å½æ°çç±»åç¾å(å 为Taskæ¯Futureçåç±»)ï¼ä½ä»Python 3.8å¼å§ï¼æ们ä¸åå 许å¨Taskä¸è°ç¨set_result()ï¼å°è¯è¿æ ·åå°å¼åRuntimeErrorãè¿ä¸ªæ³æ³æ¯ï¼ä¸ä¸ªTask代表ä¸ä¸ªæ£å¨è¿è¡çåç¨ï¼æ以ç»æåºè¯¥æ»æ¯æ¥èªäºtaskèªèº«ã
ï¼L, Lï¼ä½æ¯ï¼æ们ä»ç¶å¯ä»¥cancel()ä¸ä¸ªä»»å¡ï¼å®å°å¨åºå±åç¨ä¸å¼åCancelledErrorã
Create_task? Ensure_Future? ä¸å®å³å¿å§ï¼
å¨ç¬¬é¡µçâå¿«éå ¥é¨âä¸ï¼æ说è¿è¿è¡åç¨çæ¹æ³æ¯ä½¿ç¨asyncio.create_task()ãå¨å¼å ¥è¯¥å½æ°ä¹åï¼æå¿ è¦è·åä¸ä¸ªå¾ªç¯å®ä¾å¹¶ä½¿ç¨loop.create_task()å®æç¸åçä»»å¡ãäºå®ä¸ï¼è¿ä¹å¯ä»¥éè¿ä¸ä¸ªä¸åç模å级å½æ°æ¥å®ç°:asyncio.ensure_future()ãä¸äºå¼å人åæ¨ècreate_task()ï¼èå ¶ä»äººæ¨èensure_future()ã
å¨æ为è¿æ¬ä¹¦åç 究çè¿ç¨ä¸ï¼æ确信APIæ¹æ³asyncio.ensure_future()æ¯å¼èµ·å¯¹asyncioåºå¹¿æ³è¯¯è§£ç罪é祸é¦ãAPIç大é¨åå 容é½éå¸¸æ¸ æ°ï¼ä½å¨å¦ä¹ è¿ç¨ä¸è¿åå¨ä¸äºä¸¥éçéç¢ï¼è¿å°±æ¯å ¶ä¸ä¹ä¸ãå½ä½ éå°ensure_future()æ¶ï¼ä½ ç大èä¼é常åªåå°å°å ¶éæå°å ³äºasyncioåºè¯¥å¦ä½ä½¿ç¨çå¿ç模åä¸ââä½å¾å¯è½ä¼å¤±è´¥!
å¨Python 3.6 asyncio ææ¡£ä¸ï¼è¿ä¸ªç°å¨å·²ç»èåæèç解éçªåºäº ensure_future() çé®é¢ï¼
asyncio.ensure_future(coro_or_future, *, _loop =None)
å®ææ§è¡ä¸ä¸ªåç¨å¯¹è±¡ï¼æå®å è£ å¨futureä¸ãè¿åä¸ä¸ªTask对象ãå¦æåæ°æ¯Futureï¼åç´æ¥è¿åã
ä»ä¹!? å½æ第ä¸æ¬¡è¯»å°è¿ç¯æç« æ¶ï¼æå¾å°æãä¸é¢å¸ææ¯å¯¹ensure_future()çæ´æ¸ æ¥çæè¿°:
è¿ä¸ªå½æ°å¾å¥½å°è¯´æäºé对ç»ç«¯ç¨æ·å¼å人åçasyncio API(é«çº§API)åé对æ¡æ¶è®¾è®¡äººåçasyncio API(ä½çº§API)ä¹é´çåºå«ã让æ们å¨ç¤ºä¾ 3-ä¸èªä¹ ççå®æ¯å¦ä½å·¥ä½çã
ç¤ºä¾ 3-. ä»ç»ççensure_future()å¨åä»ä¹
ï¼L3ï¼ä¸ä¸ªç®åçä»ä¹é½ä¸åçåç¨å½æ°ãæ们åªéè¦ä¸äºè½ç»æåç¨çä¸è¥¿ã
ï¼L6ï¼æ们éè¿ç´æ¥è°ç¨è¯¥å½æ°æ¥å建åç¨å¯¹è±¡ãä½ ç代ç å¾å°ä¼è¿æ ·åï¼ä½ææ³å¨è¿éæç¡®å°è¡¨ç¤ºï¼æ们æ£å¨åæ¯ä¸ªcreate_task()åensure_future()ä¼ éä¸ä¸ªåç¨å¯¹è±¡ã
ï¼L7ï¼è·åä¸ä¸ªå¾ªç¯ã
ï¼L9ï¼é¦å ï¼æ们使ç¨loop.create_task()å¨å¾ªç¯ä¸è°åº¦åç¨ï¼å¹¶è¿åä¸ä¸ªæ°çTaskå®ä¾ã
ï¼Lï¼éªè¯ç±»åãå°ç®å为æ¢ï¼æ²¡æä»ä¹æ趣çã
ï¼Lï¼æ们å±ç¤ºäºasyncio.ensure_future()å¯ä»¥è¢«ç¨æ¥æ§è¡ä¸create_task()ç¸åçå¨ä½ï¼æä»¬ä¼ å ¥äºä¸ä¸ªåç¨ï¼å¹¶è¿åäºä¸ä¸ªTaskå®ä¾(并ä¸åç¨å·²ç»è¢«å®æå¨å¾ªç¯ä¸è¿è¡)!å¦æä¼ å ¥çæ¯åç¨ï¼é£ä¹loop.create_task()åasyncio.ensure_future()ä¹é´æ²¡æåºå«ã
ï¼Lï¼å¦ææ们ç»ensure_future()ä¼ éä¸ä¸ªTaskå®ä¾ä¼åçä»ä¹å¢ï¼æ³¨ææ们è¦ä¼ éçTaskå®ä¾æ¯å·²ç»å¨ç¬¬4æ¥éè¿loop.create_task()å建好çã
ï¼Lï¼è¿åçTaskå®ä¾ä¸ä¼ å ¥çTaskå®ä¾å®å ¨ç¸å:å®å¨è¢«ä¼ éæ¶æ²¡æ被æ¹åã
ç´æ¥ä¼ éFutureå®ä¾çæä¹ä½å¨ï¼ä¸ºä»ä¹ç¨åä¸ä¸ªå½æ°å两件ä¸åçäºæ ï¼çæ¡æ¯ï¼ensure_future()çç®çæ¯è®©æ¡æ¶ä½è åæç»ç¨æ·å¼åè æä¾å¯ä»¥å¤ç两ç§åæ°çAPIãä¸ç¸ä¿¡æï¼è¿æ¯ex-BDFLèªå·±è¯´çï¼
ensure_future()çè¦ç¹æ¯ï¼å¦æä½ æä¸ä¸ªå¯è½æ¯åç¨æFuture(åè å æ¬ä¸ä¸ªTaskï¼å 为å®æ¯Futureçåç±»)çä¸è¥¿ï¼å¹¶ä¸ä½ æ³è½å¤è°ç¨ä¸ä¸ªåªå¨Futureä¸å®ä¹çæ¹æ³(å¯è½å¯ä¸æç¨çä¾åæ¯cancel())ãå½å®å·²ç»æ¯Future(æTask)æ¶ï¼å®ä»ä¹ä¹ä¸åï¼å½å®æ¯åç¨æ¶ï¼å®å°å®å è£ å¨Taskä¸ã
å¦ææ¨ç¥éæ¨æä¸ä¸ªåç¨ï¼å¹¶ä¸å¸æå®è¢«è°åº¦ï¼é£ä¹æ£ç¡®çAPIæ¯create_task()ãå¯ä¸åºè¯¥è°ç¨ensure_future()çæ¶åæ¯å½ä½ æä¾ä¸ä¸ªAPI(å大å¤æ°asyncioèªå·±çAPI)ï¼å®æ¥ååç¨æFutureï¼ä½ éè¦å¯¹å®åä¸äºäºæ ï¼éè¦ä½ æä¸ä¸ªFutureã
âGuido van Rossum
æ»èè¨ä¹ï¼asyncio.sure_future()æ¯ä¸ä¸ªä¸ºæ¡æ¶è®¾è®¡è åå¤çè¾ å©å½æ°ãè¿ä¸ç¹æ容æéè¿ä¸ä¸ç§æ´å¸¸è§çå½æ°è¿è¡ç±»æ¯æ¥è§£éï¼æ以æ们æ¥åè¿ä¸ªè§£éãå¦æä½ æå å¹´çç¼ç¨ç»éªï¼ä½ å¯è½å·²ç»è§è¿ç±»ä¼¼äºä¾3-ä¸çistify()å½æ°çå½æ°ãç¤ºä¾ 3-ä¸listify()çå½æ°ã
ç¤ºä¾ 3-. ä¸ä¸ªå¼ºå¶è¾å ¥å表çå·¥å ·å½æ°
è¿ä¸ªå½æ°è¯å¾å°åæ°è½¬æ¢ä¸ºä¸ä¸ªå表ï¼ä¸ç®¡è¾å ¥çæ¯ä»ä¹ãapiåæ¡æ¶ä¸ç»å¸¸ä½¿ç¨è¿ç±»å½æ°å°è¾å ¥å¼ºå¶è½¬æ¢ä¸ºå·²ç¥ç±»åï¼è¿å°ç®ååç»ä»£ç ââå¨æ¬ä¾ä¸ï¼æ¨ç¥éåæ°(æ¥èªlistify()çè¾åº)å°å§ç»æ¯ä¸ä¸ªå表ã
å¦ææå°listify()å½æ°éå½å为ensure_list()ï¼é£ä¹æ¨åºè¯¥å¼å§çå°ä¸asyncio.ensure_future()ç类似ä¹å¤:å®æ»æ¯è¯å¾å°åæ°å¼ºå¶è½¬æ¢ä¸ºFuture(æåç±»)ç±»åãè¿æ¯ä¸ä¸ªå®ç¨å½æ°ï¼å®ä½¿æ¡æ¶å¼å人å(èä¸æ¯åä½ æè¿æ ·çç»ç«¯ç¨æ·å¼å人å)çå·¥ä½åå¾æ´å®¹æã
å®é ä¸ï¼asyncioæ ååºæ¨¡åæ¬èº«ä½¿ç¨ensure_future()æ£æ¯åºäºè¿ä¸ªåå ãå½ä½ ä¸æ¬¡æ¥çAPIæ¶ï¼ä½ ä¼åç°å½æ°åæ°è¢«æ述为âå¯çå¾ å¯¹è±¡âï¼å¾å¯è½å é¨ä½¿ç¨ensure_future()强å¶è½¬æ¢åæ°ãä¾å¦ï¼asyncio.gather()å½æ°å°±åä¸é¢ç代ç ä¸æ ·:
awsåæ°è¡¨ç¤ºâå¯çå¾ å¯¹è±¡âï¼å æ¬åç¨ãtaskåfutureãå¨å é¨ï¼gather()使ç¨ensure_future()è¿è¡ç±»å强å¶è½¬æ¢ï¼taskåfutureä¿æä¸åï¼èæåç¨å¼ºå¶è½¬ä¸ºtaskã
è¿éçå ³é®æ¯ï¼ä½ä¸ºç»ç«¯ç¨æ·åºç¨ç¨åºå¼å人åï¼åºè¯¥æ°¸è¿ä¸éè¦ä½¿ç¨asyncio.ensure_future()ãå®æ´åæ¯æ¡æ¶è®¾è®¡å¸çå·¥å ·ãå¦æä½ éè¦å¨äºä»¶å¾ªç¯ä¸è°åº¦åç¨ï¼åªéç´æ¥ä½¿ç¨asyncio.create_task()æ¥å®æã
å¨æ¥ä¸æ¥çå èä¸ï¼æ们å°åå°è¯è¨çº§å«çç¹æ§ï¼ä»å¼æ¥ä¸ä¸æ管çå¨å¼å§ã
python2.7.中如何引用模块做整数相除
set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。试试把list放入set,看看是否会报错
从c++协程的使用彻底搞懂协程的本质
什么是协程
协程是可中断的函数,它能够暂停执行并保存当前状态,在后续时刻恢复执行。简单来说,协程就是可以暂停和恢复的函数。
如何实现协程
例如在Python中,我们可以定义一个协程函数,并通过调用`next`函数来启动它。在执行过程中,协程可以中断,并在稍后通过再次调用`next`来恢复执行。例如:
python
def test():
print('begin')
yield
print('end')
yield
test_gen = test()
print(next(test_gen))
print(next(test_gen))
调度器
调度器是管理协程执行的关键组件。它按顺序执行协程,可以用来实现定时协程、IO协程等功能。以Python协程为例,调度器通过循环取出协程,将协程“复苏”以继续执行。
python
import asyncio
async def test():
print('begin')
await asyncio.sleep(1)
print('end')
async def main():
asyncio.ensure_future(test())
asyncio.get_event_loop().run_forever()
asyncio.run(main())
C++协程
C++标准引入了对协程的支持,允许在C++中定义协程。实现协程的关键是定义符合特定接口的函数。例如:
cpp
#include
#include
class Scheduler {
public:
void ensure_future(std::future future) {
// 将协程放入调度器的队列
}
void run_until_no_task() {
// 启动调度器执行协程
}
};
void task1() {
// 协程的实现
}
int main() {
Scheduler sche;
sche.ensure_future(std::async(std::launch::async, task1));
sche.run_until_no_task();
return 0;
}
为了使用C++协程,需要下载并编译libfuture库,该库包含了一个调度器实现。使用libfuture库,我们可以轻松创建和执行协程,如下所示:
cpp
#include
void task1() {
// 协程实现
}
int main() {
libfuture::current_scheduler().ensure_future(libfuture::async(task1));
libfuture::current_scheduler().run_until_no_task();
return 0;
}
libfuture库还提供了内置的协程,如`open_accept`、`open_connection`、`buffer_read`和`buffer_write`,用于I/O操作。通过这些协程,可以实现异步I/O,提高程序的性能。
总结
通过定义协程函数并使用调度器管理执行顺序,我们可以实现灵活的并发执行和异步操作。C++协程的引入使C++程序员能够编写更高效、更易于维护的并发程序。通过使用第三方库如libfuture,我们可以轻松实现协程功能,并利用其提供的内置协程实现复杂操作,如网络通信和文件读写等。