国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

[python] 協(xié)程學(xué)習(xí)從0到1,配合案例,徹底理解協(xié)程,耗費(fèi)資源不增加,效果接近多線程

這篇具有很好參考價(jià)值的文章主要介紹了[python] 協(xié)程學(xué)習(xí)從0到1,配合案例,徹底理解協(xié)程,耗費(fèi)資源不增加,效果接近多線程。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。


前言

多進(jìn)程和多線程在實(shí)際編程中用的已經(jīng)非常多了,這篇文章的作用是記錄下學(xué)習(xí)協(xié)程的心得體會,爭取一篇文章搞定.


協(xié)程的好處不多說了,可以說是I/O密集型的利器.其實(shí)對于IO密集型任務(wù)我們還有一種選擇就是協(xié)程。協(xié)程,又稱微線程,英文名Coroutine,是運(yùn)行在單線程中的“并發(fā)”,協(xié)程相比多線程的一大優(yōu)勢就是省去了多線程之間的切換開銷,獲得了更高的運(yùn)行效率。Python中的異步IO模塊asyncio就是基本的協(xié)程模塊。
協(xié)程的切換不同于線程切換,是由程序自身控制的,沒有切換的開銷。協(xié)程不需要多線程的鎖機(jī)制,因?yàn)槎际窃谕粋€(gè)線程中運(yùn)行,所以沒有同時(shí)訪問數(shù)據(jù)的問題,執(zhí)行效率比多線程高很多。

1.python 生成器

1.1 python 生成器概述

三個(gè)概念: 迭代/迭代器/可迭代對象
什么是生成器?
生成器也是一個(gè)可迭代對象

[num for num in range(10)]
(num for num in range(10) )

上面是一個(gè)列表,下面是一個(gè)生成器
[python] 協(xié)程學(xué)習(xí)從0到1,配合案例,徹底理解協(xié)程,耗費(fèi)資源不增加,效果接近多線程

生成器的特點(diǎn)

  1. 迭代完成一次,就指向最后一個(gè)了,再次迭代就迭代不出來了.和list不同.
    [python] 協(xié)程學(xué)習(xí)從0到1,配合案例,徹底理解協(xié)程,耗費(fèi)資源不增加,效果接近多線程
  2. 占用內(nèi)存大小不同
import sys
sys.getsizeof(10)
sys.getsizeof("Hello World")
sys.getsizeof(l)
sys.getsizeof(gen)
gen = (num for num in range(10000))
l = [num for num in range(10000)]

sys.getsizeof(l)
sys.getsizeof(gen)

[python] 協(xié)程學(xué)習(xí)從0到1,配合案例,徹底理解協(xié)程,耗費(fèi)資源不增加,效果接近多線程
生成器幾乎所占的內(nèi)存不發(fā)生變化,而列表則隨著元素的增多而增大!

生成器和列表非常類似,擁有一樣的迭代方式,內(nèi)存模型上更節(jié)省內(nèi)存空間,生成器只能遍歷一次。可以實(shí)現(xiàn)延時(shí)計(jì)算,并且用生成器代碼更簡潔。

1.2 關(guān)鍵字yield/yield from

Php, js,python C++ 中都有這個(gè)關(guān)鍵字,是一個(gè)比較高級的語法現(xiàn)象。
yield 只能再函數(shù)里面使用

def func():
	print("Hello World!");

type(func)輸出 <class ‘function’>

def func():
	print("Hello World!");
	yield()

調(diào)用func()
[python] 協(xié)程學(xué)習(xí)從0到1,配合案例,徹底理解協(xié)程,耗費(fèi)資源不增加,效果接近多線程
注意 type(func()) 他返回了一個(gè)生成器?。。?br>[python] 協(xié)程學(xué)習(xí)從0到1,配合案例,徹底理解協(xié)程,耗費(fèi)資源不增加,效果接近多線程
普通函數(shù) 調(diào)用 返回None 是因?yàn)楹瘮?shù)本來就返回none 就是普通函數(shù)的執(zhí)行。
yield 就把一個(gè)函數(shù)變成了一個(gè)生成器。

def func():
	for i in range(10):
		print(i)


def func2():
	for i in range(10):
		yield i

[python] 協(xié)程學(xué)習(xí)從0到1,配合案例,徹底理解協(xié)程,耗費(fèi)資源不增加,效果接近多線程

for i in func2():
	print(i)

同樣生成了0到9的10個(gè)數(shù)字。

1.3 next/send函數(shù)

多進(jìn)程和多線程體現(xiàn)的是操作系統(tǒng)的能力,而協(xié)程體現(xiàn)的是程序員的流程控制能力。看下面的例子,甲,乙兩個(gè)工人模擬兩個(gè)工作任務(wù)交替進(jìn)行,在單線程內(nèi)實(shí)現(xiàn)了類似多線程的功能。

import time

def task1():
    while True:
        yield "<甲>也累了,讓<乙>工作一會兒"
        time.sleep(1)
        print("<甲>工作了一段時(shí)間.....")


def task2(t):
    next(t)
    while True:
        print("-----------------------------------")
        print("<乙>工作了一段時(shí)間.....")
        time.sleep(2)
        print("<乙>累了,讓<甲>工作一會兒....")
        ret = t.send(None)
        print(ret)
    t.close()

if __name__ == '__main__':
    t = task1()
    task2(t)

輸出:

<乙>工作了一段時(shí)間.....
<乙>累了,讓<甲>工作一會兒....
<甲>工作了一段時(shí)間.....
<甲>也累了,讓<乙>工作一會兒
-----------------------------------
<乙>工作了一段時(shí)間.....
<乙>累了,讓<甲>工作一會兒....
<甲>工作了一段時(shí)間.....
<甲>也累了,讓<乙>工作一會兒
-----------------------------------
<乙>工作了一段時(shí)間.....
<乙>累了,讓<甲>工作一會兒....
<甲>工作了一段時(shí)間.....
<甲>也累了,讓<乙>工作一會兒
-----------------------------------
<乙>工作了一段時(shí)間.....

問題想一想為啥先執(zhí)行乙的語句,再執(zhí)行甲。
t = task1() 只是返回了一個(gè)生成器。task2(t) 的運(yùn)行,next(t) 使得進(jìn)入task1中執(zhí)行,并且遇到y(tǒng)ield停下,此時(shí)next(t)的返回值就是:<甲>也累了,讓<乙>工作一會兒
然后進(jìn)入task2的 while True, 直到遇到t.send(None), 執(zhí)行權(quán)反轉(zhuǎn)到task1,執(zhí)行yield的下面一句。
這里的send可以不傳none,
最早的時(shí)候,Python提供了yield關(guān)鍵字,用于制造生成器。也就是說,包含有yield的函數(shù),都是一個(gè)生成器!
yield的語法規(guī)則是:在yield這里暫停函數(shù)的執(zhí)行,并返回yield后面表達(dá)式的值(默認(rèn)為None),直到被next()方法再次調(diào)用時(shí),從上次暫停的yield代碼處繼續(xù)往下執(zhí)行。
每個(gè)生成器都可以執(zhí)行send()方法,為生成器內(nèi)部的yield語句發(fā)送數(shù)據(jù)。此時(shí)yield語句不再只是yield xxxx的形式,還可以是var = yield xxxx的賦值形式。它同時(shí)具備兩個(gè)功能,一是暫停并返回函數(shù),二是接收外部send()方法發(fā)送過來的值,重新激活函數(shù),并將這個(gè)值賦值給var變量!

def simple_coroutine():
    print('-> 啟動協(xié)程')
    y = 10
    x = yield y
    print('-> 協(xié)程接收到了x的值:', x)

my_coro = simple_coroutine()
ret = next(my_coro)
print(ret)
my_coro.send(100)
-> 啟動協(xié)程
10
-> 協(xié)程接收到了x的值: 1000
Traceback (most recent call last):
  File "c:\Users\jianming_ge\Desktop\碳匯算法第一版\carbon_code\單線程模擬多線程.py", line 54, in <module>
    my_coro.send(1000)
StopIteration

協(xié)程可以處于下面四個(gè)狀態(tài)中的一個(gè)。當(dāng)前狀態(tài)可以導(dǎo)入inspect模塊,使用inspect.getgeneratorstate(…) 方法查看,該方法會返回下述字符串中的一個(gè)。

‘GEN_CREATED’  等待開始執(zhí)行。

‘GEN_RUNNING’  協(xié)程正在執(zhí)行。

‘GEN_SUSPENDED’ 在yield表達(dá)式處暫停。

‘GEN_CLOSED’   執(zhí)行結(jié)束。

因?yàn)閟end()方法的參數(shù)會成為暫停的yield表達(dá)式的值,所以,僅當(dāng)協(xié)程處于暫停狀態(tài)時(shí)才能調(diào)用 send()方法,例如my_coro.send(10)。不過,如果協(xié)程還沒激活(狀態(tài)是’GEN_CREATED’),就立即把None之外的值發(fā)給它,會出現(xiàn)TypeError。因此,始終要先調(diào)用next(my_coro)激活協(xié)程(也可以調(diào)用my_coro.send(None)),這一過程被稱作預(yù)激活。

除了send()方法,其實(shí)還有throw()和close()方法:

generator.throw(exc_type[, exc_value[, traceback]])
使生成器在暫停的yield表達(dá)式處拋出指定的異常。如果生成器處理了拋出的異常,代碼會向前執(zhí)行到下一個(gè)yield表達(dá)式,而產(chǎn)出的值會成為調(diào)用generator.throw()方法得到的返回值。如果生成器沒有處理拋出的異常,異常會向上冒泡,傳到調(diào)用方的上下文中。

generator.close()
使生成器在暫停的yield表達(dá)式處拋出GeneratorExit異常。如果生成器沒有處理這個(gè)異常,或者拋出了StopIteration異常(通常是指運(yùn)行到結(jié)尾),調(diào)用方不會報(bào)錯(cuò)。如果收到GeneratorExit異常,生成器一定不能產(chǎn)出值,否則解釋器會拋出RuntimeError異常。生成器拋出的其他異常會向上冒泡,傳給調(diào)用方。

1.4 StopInteration異常

平時(shí)在進(jìn)行python編程的時(shí)候,一般不關(guān)注異常,但學(xué)習(xí)生成器的時(shí)候,需要利用這個(gè)stopinteration進(jìn)行編程

1.5 利用生成器實(shí)現(xiàn)生產(chǎn)者-消費(fèi)者模型

1.6 生成器和協(xié)程的關(guān)系

[python] 協(xié)程學(xué)習(xí)從0到1,配合案例,徹底理解協(xié)程,耗費(fèi)資源不增加,效果接近多線程

生成器通過yield可以主動讓出cpu
多個(gè)生成器可以共同使用cpu,共同協(xié)作,有序進(jìn)行
生成器可以進(jìn)一步封裝成協(xié)程

2.生成器協(xié)程調(diào)度器

3.python事件驅(qū)動編程

4.實(shí)現(xiàn)協(xié)程調(diào)度器

5.python 協(xié)程生態(tài)

@asyncio.coroutine與yield from
@asyncio.coroutine:asyncio模塊中的裝飾器,用于將一個(gè)生成器聲明為協(xié)程。
下面這段代碼,我們創(chuàng)造了一個(gè)協(xié)程display_date(num, loop),然后它使用關(guān)鍵字yield from來等待協(xié)程asyncio.sleep(2)()的返回結(jié)果。而在這等待的2s之間它會讓出CPU的執(zhí)行權(quán),直到asyncio.sleep(2)返回結(jié)果。asyncio.sleep(2)模擬的其實(shí)就是一個(gè)耗時(shí)2秒的IO讀寫操作。

import asyncio
import datetime

@asyncio.coroutine  # 聲明一個(gè)協(xié)程
def display_date(num, loop):
    end_time = loop.time() + 10.0
    while True:
        print("Loop: {} Time: {}".format(num, datetime.datetime.now()))
        if (loop.time() + 1.0) >= end_time:
            break
        yield from asyncio.sleep(2)  # 阻塞直到協(xié)程sleep(2)返回結(jié)果
loop = asyncio.get_event_loop()  # 獲取一個(gè)event_loop
tasks = [display_date(1, loop), display_date(2, loop)]
loop.run_until_complete(asyncio.gather(*tasks))  # "阻塞"直到所有的tasks完成
loop.close()

Python3.5中對協(xié)程提供了更直接的支持,引入了async/await關(guān)鍵字。上面的代碼可以這樣改寫:使用async代替@asyncio.coroutine,使用await代替yield from,代碼變得更加簡潔可讀。從Python設(shè)計(jì)的角度來說,async/await讓協(xié)程獨(dú)立于生成器而存在,不再使用yield語法。

import asyncio
import datetime

async def display_date(num, loop):      # 注意這一行的寫法
    end_time = loop.time() + 10.0
    while True:
        print("Loop: {} Time: {}".format(num, datetime.datetime.now()))
        if (loop.time() + 1.0) >= end_time:
            break
        await asyncio.sleep(2)  # 阻塞直到協(xié)程sleep(2)返回結(jié)果

loop = asyncio.get_event_loop()  # 獲取一個(gè)event_loop
tasks = [display_date(1, loop), display_date(2, loop)]
loop.run_until_complete(asyncio.gather(*tasks))  # "阻塞"直到所有的tasks完成
loop.close()

asyncio模塊
asyncio的使用可分三步走:

創(chuàng)建事件循環(huán)
指定循環(huán)模式并運(yùn)行
關(guān)閉循環(huán)
通常我們使用asyncio.get_event_loop()方法創(chuàng)建一個(gè)循環(huán)。

運(yùn)行循環(huán)有兩種方法:一是調(diào)用run_until_complete()方法,二是調(diào)用run_forever()方法。run_until_complete()內(nèi)置add_done_callback回調(diào)函數(shù),run_forever()則可以自定義add_done_callback(),具體差異請看下面兩個(gè)例子。

使用run_until_complete()方法:

import asyncio

async def func(future):
    await asyncio.sleep(1)
    future.set_result('Future is done!')

if __name__ == '__main__':

    loop = asyncio.get_event_loop()
    future = asyncio.Future()
    asyncio.ensure_future(func(future))
    print(loop.is_running())   # 查看當(dāng)前狀態(tài)時(shí)循環(huán)是否已經(jīng)啟動
    loop.run_until_complete(future)
    print(future.result())
    loop.close()

使用run_forever()方法:文章來源地址http://www.zghlxwxcb.cn/news/detail-433386.html

import asyncio

async def func(future):
    await asyncio.sleep(1)
    future.set_result('Future is done!')

def call_result(future):
    print(future.result())
    loop.stop()

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    future = asyncio.Future()
    asyncio.ensure_future(func(future))
    future.add_done_callback(call_result)        # 注意這行
    try:
        loop.run_forever()
    finally:
        loop.close()

到了這里,關(guān)于[python] 協(xié)程學(xué)習(xí)從0到1,配合案例,徹底理解協(xié)程,耗費(fèi)資源不增加,效果接近多線程的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【深度學(xué)習(xí)筆記】徹底理解torch中的tensor與numpy中array區(qū)別及用法

    剛接觸深度學(xué)習(xí)的同學(xué),很多開源項(xiàng)目代碼中, 張量tensor 與 數(shù)組array 都有使用,不清楚兩者有什么區(qū)別,以及怎么使用,如何相互轉(zhuǎn)換等。博主起初也有類似的疑惑,經(jīng)過查閱資料以及實(shí)踐,逐漸有了深入了解,本文將記錄并分享自己對兩者的理解,可供參考。 提示:以下

    2023年04月08日
    瀏覽(81)
  • Python學(xué)習(xí)之路-多任務(wù):協(xié)程

    協(xié)程,又稱微線程,纖程。英文名Coroutine。協(xié)程是python個(gè)中另外一種實(shí)現(xiàn)多任務(wù)的方式,只不過比線程更小占用更小執(zhí)行單元(理解為需要的資源)。 為啥說它是一個(gè)執(zhí)行單元,因?yàn)樗詭PU上下文。這樣只要在合適的時(shí)機(jī), 我們可以把一個(gè)協(xié)程 切換到另一個(gè)協(xié)程。 只要這

    2024年01月17日
    瀏覽(19)
  • 某省公共資源交易電子公共服務(wù)平臺學(xué)習(xí)案例

    某省公共資源交易電子公共服務(wù)平臺學(xué)習(xí)案例

    聲明:本文僅限學(xué)習(xí)交流使用,禁止用于非法用途、商業(yè)活動等。否則后果自負(fù)。如有侵權(quán),請告知刪除,謝謝!本教程也沒有專門針對某個(gè)網(wǎng)站而編寫,單純的技術(shù)研究 目標(biāo)案例:aHR0cHM6Ly9nZ3p5ZncuZnVqaWFuLmdvdi5jbi9idXNpbmVzcy9saXN0Lw== 1.對應(yīng)接口 2.對應(yīng)難點(diǎn) 參數(shù)加密 數(shù)據(jù)加密 通過

    2024年02月08日
    瀏覽(20)
  • 從零開始學(xué)習(xí)iftop流量監(jiān)控(找出服務(wù)器耗費(fèi)流量最多的ip和端口)

    從零開始學(xué)習(xí)iftop流量監(jiān)控(找出服務(wù)器耗費(fèi)流量最多的ip和端口)

    iftop是類似于top的實(shí)時(shí)流量監(jiān)控工具。 作用:監(jiān)控網(wǎng)卡的實(shí)時(shí)流量(可以指定網(wǎng)段)、反向解析IP、顯示端口信息等 官網(wǎng): http://www.ex-parrot.com/~pdw/iftop/ 一般參數(shù) 主機(jī)參數(shù) 端口顯示參數(shù) 輸出排序參數(shù) 1.顯示網(wǎng)卡eth0的信息,主機(jī)通過ip顯示 2.顯示端口號(添加-P參數(shù),進(jìn)入界面

    2023年04月08日
    瀏覽(28)
  • 深入理解 Golang: Goroutine 協(xié)程

    深入理解 Golang: Goroutine 協(xié)程

    進(jìn)程用來分配內(nèi)存空間,是操作系統(tǒng)分配資源的最小單位;線程用來分配 CPU 時(shí)間,多個(gè)線程共享內(nèi)存空間,是操作系統(tǒng)或 CPU 調(diào)度的最小單位;協(xié)程用來精細(xì)利用線程。協(xié)程就是將一段程序的運(yùn)行狀態(tài)打包,可以在線程之間調(diào)度?;蛘哒f將一段生產(chǎn)流程打包,使流程不固定在

    2024年02月11日
    瀏覽(20)
  • 最新完整熱更新實(shí)戰(zhàn)案例學(xué)習(xí),包括資源熱更新及代碼熱更新【文末送書】

    最新完整熱更新實(shí)戰(zhàn)案例學(xué)習(xí),包括資源熱更新及代碼熱更新【文末送書】

    ?? 博客主頁:https://xiaoy.blog.csdn.net ?? 本文由 呆呆敲代碼的小Y 原創(chuàng),首發(fā)于 CSDN ?? ?? 學(xué)習(xí)專欄推薦:Unity系統(tǒng)學(xué)習(xí)專欄 ?? 游戲制作專欄推薦:游戲制作 ??Unity實(shí)戰(zhàn)100例專欄推薦:Unity 實(shí)戰(zhàn)100例 教程 ?? 歡迎點(diǎn)贊 ?? 收藏 ?留言 ?? 如有錯(cuò)誤敬請指正! ?? 未來很長

    2023年04月08日
    瀏覽(18)
  • Python 華為面試手撕代碼 + 八股文,機(jī)器學(xué)習(xí)參數(shù)調(diào)節(jié),損失函數(shù),激活函數(shù),線程、進(jìn)程和協(xié)程

    Python 華為面試手撕代碼 + 八股文,機(jī)器學(xué)習(xí)參數(shù)調(diào)節(jié),損失函數(shù),激活函數(shù),線程、進(jìn)程和協(xié)程

    一、手撕代碼:力扣原題905 二、八股文部分:有點(diǎn)緊張,忘了好多東西 1.深度學(xué)習(xí)模型優(yōu)化的方法有哪些? 深度學(xué)習(xí)模型的優(yōu)化策略包括以下幾個(gè)方面: (1)選擇合適的激活函數(shù):激活函數(shù)對模型的表達(dá)能力和收斂速度有很大影響,常用的激活函數(shù)包括ReLU、Sigmoid、Tanh等。

    2024年02月09日
    瀏覽(23)
  • 主成分分析法(PCA)的理解(附python代碼案例)

    主成分分析法(PCA)的理解(附python代碼案例)

    最近在文獻(xiàn)調(diào)研,發(fā)現(xiàn)PCA基本都有用到,回憶起了機(jī)器學(xué)習(xí)和數(shù)學(xué)建模,總之還是要好好學(xué)學(xué)捏。 定義 :主成分分析(Principal Component Analysis, PCA)是一種統(tǒng)計(jì)方法。通過正交變換將一組可能存在相關(guān)性的變量轉(zhuǎn)換為一組線性不相關(guān)的變量,轉(zhuǎn)換后的這組變量叫主成分。 換一

    2024年02月03日
    瀏覽(21)
  • Unity 熱更新技術(shù) |(七)完整熱更新實(shí)戰(zhàn)案例學(xué)習(xí)使用,包括資源熱更新及代碼熱更新【文末書】

    Unity 熱更新技術(shù) |(七)完整熱更新實(shí)戰(zhàn)案例學(xué)習(xí)使用,包括資源熱更新及代碼熱更新【文末書】

    ?? 博客主頁:https://xiaoy.blog.csdn.net ?? 本文由 呆呆敲代碼的小Y 原創(chuàng),首發(fā)于 CSDN ?? ?? 學(xué)習(xí)專欄推薦:Unity系統(tǒng)學(xué)習(xí)專欄 ?? 游戲制作專欄推薦:游戲制作 ??Unity實(shí)戰(zhàn)100例專欄推薦:Unity 實(shí)戰(zhàn)100例 教程 ?? 歡迎點(diǎn)贊 ?? 收藏 ?留言 ?? 如有錯(cuò)誤敬請指正! ?? 未來很長

    2023年04月17日
    瀏覽(27)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包