成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Python中的asyncio庫(kù)-asyncio的概念是什么

不懂Python中的asyncio庫(kù)-asyncio的概念是什么?其實(shí)想解決這個(gè)問(wèn)題也不難,下面讓小編帶著大家一起學(xué)習(xí)怎么去解決,希望大家閱讀完這篇文章后大所收獲。

創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),哈爾濱企業(yè)網(wǎng)站建設(shè),哈爾濱品牌網(wǎng)站建設(shè),網(wǎng)站定制,哈爾濱網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷(xiāo),網(wǎng)絡(luò)優(yōu)化,哈爾濱網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力。可充分滿(mǎn)足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專(zhuān)業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶(hù)成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

核心概念

asyncio里面主要有4個(gè)需要關(guān)注的基本概念

Eventloop

Eventloop可以說(shuō)是asyncio應(yīng)用的核心,是中央總控。Eventloop實(shí)例提供了注冊(cè)、取消和執(zhí)行任務(wù)和回調(diào)的方法。

把一些異步函數(shù)(就是任務(wù),Task,一會(huì)就會(huì)說(shuō)到)注冊(cè)到這個(gè)事件循環(huán)上,事件循環(huán)會(huì)循環(huán)執(zhí)行這些函數(shù)(但同時(shí)只能執(zhí)行一個(gè)),當(dāng)執(zhí)行到某個(gè)函數(shù)時(shí),如果它正在等待I/O返回,事件循環(huán)會(huì)暫停它的執(zhí)行去執(zhí)行其他的函數(shù);當(dāng)某個(gè)函數(shù)完成I/O后會(huì)恢復(fù),下次循環(huán)到它的時(shí)候繼續(xù)執(zhí)行。因此,這些異步函數(shù)可以協(xié)同(Cooperative)運(yùn)行:這就是事件循環(huán)的目標(biāo)。

Coroutine

協(xié)程(Coroutine)本質(zhì)上是一個(gè)函數(shù),特點(diǎn)是在代碼塊中可以將執(zhí)行權(quán)交給其他協(xié)程:

? cat coro1.py
import asyncio
async def a():
    print('Suspending a')
    await asyncio.sleep(0)
    print('Resuming a')
async def b():
    print('In b')
async def main():
    await asyncio.gather(a(), b())
if __name__ == '__main__':
    asyncio.run(main())

這里面有4個(gè)重要關(guān)鍵點(diǎn):

協(xié)程要用async def聲明,Python 3.5時(shí)的裝飾器寫(xiě)法已經(jīng)過(guò)時(shí),我就不列出來(lái)了。

asyncio.gather用來(lái)并發(fā)運(yùn)行任務(wù),在這里表示協(xié)同的執(zhí)行a和b2個(gè)協(xié)程

在協(xié)程a中,有一句await asyncio.sleep(0),await表示調(diào)用協(xié)程,sleep 0并不會(huì)真的sleep(因?yàn)闀r(shí)間為0),但是卻可以把控制權(quán)交出去了。

asyncio.run是Python 3.7新加的接口,要不然你得這么寫(xiě):

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

好了,我們先運(yùn)行一下看看:

? python coro1.py
Suspending a
In b
Resuming a

看到了吧,在并發(fā)執(zhí)行中,協(xié)程a被掛起又恢復(fù)過(guò)。

Future

接著說(shuō)Future,它代表了一個(gè)「未來(lái)」對(duì)象,異步操作結(jié)束后會(huì)把最終結(jié)果設(shè)置到這個(gè)Future對(duì)象上。Future是對(duì)協(xié)程的封裝,不過(guò)日常開(kāi)發(fā)基本是不需要直接用這個(gè)底層Future類(lèi)的。我在這里只是演示一下:

In : def c():
...:     print('Inner C')
...:     return 12
...:
In : future = loop.run_in_executor(None, c)  # 這里沒(méi)用await,None 表示默認(rèn)的 executor
Inner C
In : future  # 雖然c已經(jīng)執(zhí)行了,但是狀態(tài)還是 pending。
Out: <Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/local/lib/python3.7/asyncio/futures.py:348]>
In : future.done()  # 還沒(méi)有完成
Out: False
In : for a in dir(future):
...:     if not a.startswith('_'):
...:         print(a)
...:
add_done_callback
cancel
cancelled
done
exception
get_loop
remove_done_callback
result
set_exception
set_result

可以對(duì)這個(gè)Future實(shí)例添加完成后的回調(diào)(add_done_callback)、取消任務(wù)(cancel)、設(shè)置最終結(jié)果(set_result)、設(shè)置異常(如果有的話(huà),set_exception)等?,F(xiàn)在我們讓Future完成:

In : await future
Out: 12
In : future
Out: <Future finished result=12>
In : future.done()
Out: True
In : future.result()
Out: 12

看到了吧,await之后狀態(tài)成了finished。這里順便說(shuō)一下,一個(gè)對(duì)象怎么樣就可以被await(或者說(shuō)怎么樣就成了一個(gè)awaitable對(duì)象)呢?給類(lèi)實(shí)現(xiàn)一個(gè)__await__方法,Python版本的Future的實(shí)現(xiàn)大概如下:

def __await_(self):
    if not self.done():
        self._asyncio_future_blocking = True
        yield self
    if not self.done():
        raise RuntimeError("await wasn't used with future")
    return self.result()

這樣就可以await future了,那為什么await future后Future的狀態(tài)就能改變呢,這是因?yàn)橛胠oop.run_in_executor創(chuàng)建的Future注冊(cè)了一個(gè)回調(diào)(通過(guò)asyncio.futures.wrap_future,加了一個(gè)_call_set_state回調(diào), 有興趣的可以通過(guò)延伸閱讀鏈接2找上下文)。

__await__里面的yield self不要奇怪,主要是為了兼容__iter__,給舊的yield from用:

In : future = loop.run_in_executor(None, c)
Inner C
In : future
Out: <Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/local/lib/python3.7/asyncio/futures.py:348]>
In : def spam():
...:     yield from future
...:
In : s = spam()
In : next(s)
Out: <Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/local/lib/python3.7/asyncio/futures.py:348]>
新的替代yield from的用法await必須在異步函數(shù)(用 async def申明)中使用:
In : def spam():
...:     await future
...:
  File "cell_name", line 5
SyntaxError: 'await' outside async function

Task

Eventloop除了支持協(xié)程,還支持注冊(cè)Future和Task2種類(lèi)型的對(duì)象,那為什么要存在Future和Task這2種類(lèi)型呢?

先回憶前面的例子,F(xiàn)uture是協(xié)程的封裝,F(xiàn)uture對(duì)象提供了很多任務(wù)方法(如完成后的回調(diào)、取消、設(shè)置任務(wù)結(jié)果等等),但是開(kāi)發(fā)者并不需要直接操作Future這種底層對(duì)象,而是用Future的子類(lèi)Task協(xié)同的調(diào)度協(xié)程以實(shí)現(xiàn)并發(fā)。

Task非常容易創(chuàng)建和使用:

# 或者用task = loop.create_task(a())
In : task = asyncio.ensure_future(a())
In : task
Out: <Task pending coro=<a() running at /Users/dongwm/mp/2019-05-22/coro1.py:4>>
In : task.done()
Out: False
In : await task
Suspending a
Resuming a
In : task
Out: <Task finished coro=<a() done, defined at /Users/dongwm/mp/2019-05-22/coro1.py:4> result=None>
In : task.done()
Out: True

asyncio并發(fā)的正確/錯(cuò)誤姿勢(shì)

在代碼中使用async/await是不是就能發(fā)揮asyncio的并發(fā)優(yōu)勢(shì)么,其實(shí)是不對(duì)的,我們先看個(gè)例子:

async def a():
    print('Suspending a')
    await asyncio.sleep(3)
    print('Resuming a')
async def b():
    print('Suspending b')
    await asyncio.sleep(1)
    print('Resuming b')
async def s1():
    await a()
    await b()

有2個(gè)協(xié)程a和b,分別sleep1秒和3秒,如果協(xié)程可以并發(fā)執(zhí)行,那么執(zhí)行時(shí)間應(yīng)該是sleep最大的那個(gè)值(3秒),現(xiàn)在它們都在s1協(xié)程里面被調(diào)用。大家先猜一下s1會(huì)運(yùn)行幾秒?

我們寫(xiě)個(gè)小程序驗(yàn)證一下:

def show_perf(func):
    print('*' * 20)
    start = time.perf_counter()
    asyncio.run(func())
    print(f'{func.__name__} Cost: {time.perf_counter() - start}')

大家注意我這個(gè)時(shí)間計(jì)數(shù)用的方法,沒(méi)有用time.time,而是用了Python 3.3新增的time.perf_counter它是現(xiàn)在推薦的用法。我們?cè)贗Python里面驗(yàn)證下:

In : from coro2 import *
In : show_perf(s1)
********************
Suspending a
Resuming a
Suspending b
Resuming b
s1 Cost: 4.009796932999961

看到了吧,4秒?。?!,相當(dāng)于串行的執(zhí)行了(sleep 3 + 1)。這是錯(cuò)誤的用法,應(yīng)該怎么用呢,前面的asyncio.gather就可以:

async def c1():
    await asyncio.gather(a(), b())
In : show_perf(c1)
********************
Suspending a
Suspending b
Resuming b
Resuming a
c1 Cost: 3.002452698999832

看到了吧,3秒!另外一個(gè)是asyncio.wait:

async def c2():
    await asyncio.wait([a(), b()])
In : show_perf(c2)
...
c2 Cost: 3.0066957049998564

同樣是3秒。先別著急,gather和wait下篇文章還會(huì)繼續(xù)對(duì)比。還有一個(gè)方案就是用asyncio.create_task:

async def c3():
    task1 = asyncio.create_task(a())
    task2 = asyncio.create_task(b())
    await task1
    await task2
async def c4():
    task = asyncio.create_task(b())
    await a()
    await task
In : show_perf(c3)
...
c3 Cost: 3.002332438999929
In : show_perf(c4)
...
c4 Cost: 3.002270970000154

都是3秒。asyncio.create_task相當(dāng)于把協(xié)程封裝成Task。不過(guò)大家要注意一個(gè)錯(cuò)誤的用法:

async def s2():
    await asyncio.create_task(a())
    await asyncio.create_task(b())
In : show_perf(s2)
...
s2 Cost: 4.004671427999938

直接await task不會(huì)對(duì)并發(fā)有幫助*。asyncio.create_task是Python 3.7新增的高階API,是推薦的用法,其實(shí)你還可以用

asyncio.ensure_future和loop.create_task:
async def c5():
    task = asyncio.ensure_future(b())
    await a()
    await task
async def c6():
    loop = asyncio.get_event_loop()
    task = loop.create_task(b())
    await a()
    await task
In : show_perf(c5)
...
c5 Cost: 3.0033873750003295
In : show_perf(c6)
...
c6 Cost: 3.006120122000084

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享Python中的asyncio庫(kù)-asyncio的概念是什么內(nèi)容對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,遇到問(wèn)題就找創(chuàng)新互聯(lián),詳細(xì)的解決方法等著你來(lái)學(xué)習(xí)!

標(biāo)題名稱(chēng):Python中的asyncio庫(kù)-asyncio的概念是什么
網(wǎng)頁(yè)地址:http://jinyejixie.com/article24/ghhcje.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、網(wǎng)站設(shè)計(jì)、關(guān)鍵詞優(yōu)化、網(wǎng)站改版、電子商務(wù)、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)
高阳县| 略阳县| 阳曲县| 威远县| 尼勒克县| 通州市| 东乌珠穆沁旗| 金坛市| 南投县| 竹山县| 岳阳市| 三都| 济源市| 桦南县| 鲁甸县| 黄山市| 丰顺县| 潼关县| 大兴区| 郯城县| 安乡县| 来宾市| 淳化县| 石泉县| 商南县| 万盛区| 苍梧县| 新丰县| 黄梅县| 汉川市| 郸城县| 铜鼓县| 铁岭县| 疏勒县| 溆浦县| 长兴县| 巴马| 靖远县| 华容县| 大兴区| 卫辉市|