真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

python轉(zhuǎn)化異步函數(shù) python 異步

python2.7怎么實(shí)現(xiàn)異步

改進(jìn)之前

在思明等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專(zhuān)注、極致的服務(wù)理念,為客戶(hù)提供做網(wǎng)站、成都網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作按需求定制開(kāi)發(fā),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),全網(wǎng)營(yíng)銷(xiāo)推廣,外貿(mào)網(wǎng)站制作,思明網(wǎng)站建設(shè)費(fèi)用合理。

之前,我的查詢(xún)步驟很簡(jiǎn)單,就是:

前端提交查詢(xún)請(qǐng)求 -- 建立數(shù)據(jù)庫(kù)連接 -- 新建游標(biāo) -- 執(zhí)行命令 -- 接受結(jié)果 -- 關(guān)閉游標(biāo)、連接

這幾大步驟的順序執(zhí)行。

這里面當(dāng)然問(wèn)題很大:

建立數(shù)據(jù)庫(kù)連接實(shí)際上就是新建一個(gè)套接字。這是進(jìn)程間通信的幾種方法里,開(kāi)銷(xiāo)最大的了。

在“執(zhí)行命令”和“接受結(jié)果”兩個(gè)步驟中,線(xiàn)程在阻塞在數(shù)據(jù)庫(kù)內(nèi)部的運(yùn)行過(guò)程中,數(shù)據(jù)庫(kù)連接和游標(biāo)都處于閑置狀態(tài)。

這樣一來(lái),每一次查詢(xún)都要順序的新建數(shù)據(jù)庫(kù)連接,都要阻塞在數(shù)據(jù)庫(kù)返回結(jié)果的過(guò)程中。當(dāng)前端提交大量查詢(xún)請(qǐng)求時(shí),查詢(xún)效率肯定是很低的。

第一次改進(jìn)

之前的模塊里,問(wèn)題最大的就是第一步——建立數(shù)據(jù)庫(kù)連接套接字了。如果能夠一次性建立連接,之后查詢(xún)能夠反復(fù)服用這個(gè)連接就好了。

所以,首先應(yīng)該把數(shù)據(jù)庫(kù)查詢(xún)模塊作為一個(gè)單獨(dú)的守護(hù)進(jìn)程去執(zhí)行,而前端app作為主進(jìn)程響應(yīng)用戶(hù)的點(diǎn)擊操作。那么兩條進(jìn)程怎么傳遞消息呢?翻了幾天Python文檔,終于構(gòu)思出來(lái):用隊(duì)列queue作為生產(chǎn)者(web前端)向消費(fèi)者(數(shù)據(jù)庫(kù)后端)傳遞任務(wù)的渠道。生產(chǎn)者,會(huì)與SQL命令一起,同時(shí)傳遞一個(gè)管道pipe的連接對(duì)象,作為任務(wù)完成后,回傳結(jié)果的渠道。確保,任務(wù)的接收方與發(fā)送方保持一致。

作為第二個(gè)問(wèn)題的解決方法,可以使用線(xiàn)程池來(lái)并發(fā)獲取任務(wù)隊(duì)列中的task,然后執(zhí)行命令并回傳結(jié)果。

第二次改進(jìn)

第一次改進(jìn)的效果還是很明顯的,不用任何測(cè)試手段。直接點(diǎn)擊頁(yè)面鏈接,可以很直觀地感覺(jué)到反應(yīng)速度有很明顯的加快。

但是對(duì)于第二個(gè)問(wèn)題,使用線(xiàn)程池還是有些欠妥當(dāng)。因?yàn)?,CPython解釋器存在GIL問(wèn)題,所有線(xiàn)程實(shí)際上都在一個(gè)解釋器進(jìn)程里調(diào)度。線(xiàn)程稍微開(kāi)多一點(diǎn),解釋器進(jìn)程就會(huì)頻繁的切換線(xiàn)程,而線(xiàn)程切換的開(kāi)銷(xiāo)也不小。線(xiàn)程多一點(diǎn),甚至?xí)霈F(xiàn)“抖動(dòng)”問(wèn)題(也就是剛剛喚醒一個(gè)線(xiàn)程,就進(jìn)入掛起狀態(tài),剛剛換到棧幀或內(nèi)存的上下文,又被換回內(nèi)存或者磁盤(pán)),效率大大降低。也就是說(shuō),線(xiàn)程池的并發(fā)量很有限。

試過(guò)了多進(jìn)程、多線(xiàn)程,只能在單個(gè)線(xiàn)程里做文章了。

Python中的asyncio庫(kù)

Python里有大量的協(xié)程庫(kù)可以實(shí)現(xiàn)單線(xiàn)程內(nèi)的并發(fā)操作,比如Twisted、Gevent等等。Python官方在3.5版本里提供了asyncio庫(kù)同樣可以實(shí)現(xiàn)協(xié)程并發(fā)。asyncio庫(kù)大大降低了Python中協(xié)程的實(shí)現(xiàn)難度,就像定義普通函數(shù)那樣就可以了,只是要在def前面多加一個(gè)async關(guān)鍵詞。async def函數(shù)中,需要阻塞在其他async def函數(shù)的位置前面可以加上await關(guān)鍵詞。

import asyncio

async def wait():

await asyncio.sleep(2)

async def execute(task):

process_task(task)

await wait()

continue_job()

async def函數(shù)的執(zhí)行稍微麻煩點(diǎn)。需要首先獲取一個(gè)loop對(duì)象,然后由這個(gè)對(duì)象代為執(zhí)行async def函數(shù)。

loop = asyncio.get_event_loop()

loop.run_until_complete(execute(task))

loop.close()

loop在執(zhí)行execute(task)函數(shù)時(shí),如果遇到await關(guān)鍵字,就會(huì)暫時(shí)掛起當(dāng)前協(xié)程,轉(zhuǎn)而去執(zhí)行其他阻塞在await關(guān)鍵詞的協(xié)程,從而實(shí)現(xiàn)協(xié)程并發(fā)。

不過(guò)需要注意的是,run_until_complete()函數(shù)本身是一個(gè)阻塞函數(shù)。也就是說(shuō),當(dāng)前線(xiàn)程會(huì)等候一個(gè)run_until_complete()函數(shù)執(zhí)行完畢之后,才會(huì)繼續(xù)執(zhí)行下一部函數(shù)。所以下面這段代碼并不能并發(fā)執(zhí)行。

for task in task_list:

loop.run_until_complete(task)

對(duì)與這個(gè)問(wèn)題,asyncio庫(kù)也有相應(yīng)的解決方案:gather函數(shù)。

loop = asyncio.get_event_loop()

tasks = [asyncio.ensure_future(execute(task))

for task in task_list]

loop.run_until_complete(asyncio.gather(*tasks))

loop.close()

當(dāng)然了,async def函數(shù)的執(zhí)行并不只有這兩種解決方案,還有call_soon與run_forever的配合執(zhí)行等等,更多內(nèi)容還請(qǐng)參考官方文檔。

Python下的I/O多路復(fù)用

協(xié)程,實(shí)際上,也存在上下文切換,只不過(guò)開(kāi)銷(xiāo)很輕微。而I/O多路復(fù)用則完全不存在這個(gè)問(wèn)題。

目前,Linux上比較火的I/O多路復(fù)用API要算epoll了。Tornado,就是通過(guò)調(diào)用C語(yǔ)言封裝的epoll庫(kù),成功解決了C10K問(wèn)題(當(dāng)然還有Pypy的功勞)。

在Linux里查文檔,可以看到epoll只有三類(lèi)函數(shù),調(diào)用起來(lái)比較方便易懂。

創(chuàng)建epoll對(duì)象,并返回其對(duì)應(yīng)的文件描述符(file descriptor)。

int epoll_create(int size);

int epoll_create1(int flags);

控制監(jiān)聽(tīng)事件。第一個(gè)參數(shù)epfd就對(duì)應(yīng)于前面命令創(chuàng)建的epoll對(duì)象的文件描述符;第二個(gè)參數(shù)表示該命令要執(zhí)行的動(dòng)作:監(jiān)聽(tīng)事件的新增、修改或者刪除;第三個(gè)參數(shù),是要監(jiān)聽(tīng)的文件對(duì)應(yīng)的描述符;第四個(gè),代表要監(jiān)聽(tīng)的事件。

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

等候。這是一個(gè)阻塞函數(shù),調(diào)用者會(huì)等候內(nèi)核通知所注冊(cè)的事件被觸發(fā)。

int epoll_wait(int epfd, struct epoll_event *events,

int maxevents, int timeout);

int epoll_pwait(int epfd, struct epoll_event *events,

int maxevents, int timeout,

const sigset_t *sigmask);

在Python的select庫(kù)里:

select.epoll()對(duì)應(yīng)于第一類(lèi)創(chuàng)建函數(shù);

epoll.register(),epoll.unregister(),epoll.modify()均是對(duì)控制函數(shù)epoll_ctl的封裝;

epoll.poll()則是對(duì)等候函數(shù)epoll_wait的封裝。

Python里epoll相關(guān)API的最大問(wèn)題應(yīng)該是在epoll.poll()。相比于其所封裝的epoll_wait,用戶(hù)無(wú)法手動(dòng)指定要等候的事件,也就是后者的第二個(gè)參數(shù)struct epoll_event *events。沒(méi)法實(shí)現(xiàn)精確控制。因此只能使用替代方案:select.select()函數(shù)。

根據(jù)Python官方文檔,select.select(rlist, wlist, xlist[, timeout])是對(duì)Unix系統(tǒng)中select函數(shù)的直接調(diào)用,與C語(yǔ)言API的傳參很接近。前三個(gè)參數(shù)都是列表,其中的元素都是要注冊(cè)到內(nèi)核的文件描述符。如果想用自定義類(lèi),就要確保實(shí)現(xiàn)了fileno()方法。

其分別對(duì)應(yīng)于:

rlist: 等候直到可讀

wlist: 等候直到可寫(xiě)

xlist: 等候直到異常。這個(gè)異常的定義,要查看系統(tǒng)文檔。

select.select(),類(lèi)似于epoll.poll(),先注冊(cè)文件和事件,然后保持等候內(nèi)核通知,是阻塞函數(shù)。

實(shí)際應(yīng)用

Psycopg2庫(kù)支持對(duì)異步和協(xié)程,但和一般情況下的用法略有區(qū)別。普通數(shù)據(jù)庫(kù)連接支持不同線(xiàn)程中的不同游標(biāo)并發(fā)查詢(xún);而異步連接則不支持不同游標(biāo)的同時(shí)查詢(xún)。所以異步連接的不同游標(biāo)之間必須使用I/O復(fù)用方法來(lái)協(xié)調(diào)調(diào)度。

所以,我的大致實(shí)現(xiàn)思路是這樣的:首先并發(fā)執(zhí)行大量協(xié)程,從任務(wù)隊(duì)列中提取任務(wù),再向連接池請(qǐng)求連接,創(chuàng)建游標(biāo),然后執(zhí)行命令,并返回結(jié)果。在獲取游標(biāo)和接受查詢(xún)結(jié)果之前,均要阻塞等候內(nèi)核通知連接可用。

其中,連接池返回連接時(shí),會(huì)根據(jù)引用連接的協(xié)程數(shù)量,返回負(fù)載最輕的連接。這也是自己定義AsyncConnectionPool類(lèi)的目的。

我的代碼位于:bottle-blog/dbservice.py

存在問(wèn)題

當(dāng)然了,這個(gè)流程目前還一些問(wèn)題。

首先就是每次輪詢(xún)拿到任務(wù)之后,都會(huì)走這么一個(gè)流程。

獲取連接 -- 新建游標(biāo) -- 執(zhí)行任務(wù) -- 關(guān)閉游標(biāo) -- 取消連接引用

本來(lái),最好的情況應(yīng)該是:在輪詢(xún)之前,就建好游標(biāo);在輪詢(xún)時(shí),直接等候內(nèi)核通知,執(zhí)行相應(yīng)任務(wù)。這樣可以減少輪詢(xún)時(shí)的任務(wù)量。但是如果協(xié)程提前對(duì)應(yīng)好連接,那就不能保證在獲取任務(wù)時(shí),保持各連接負(fù)載均衡了。

所以這一塊,還有工作要做。

還有就是epoll沒(méi)能用上,有些遺憾。

以后打算寫(xiě)點(diǎn)C語(yǔ)言的內(nèi)容,或者用Python/C API,或者用Ctypes包裝共享庫(kù),來(lái)實(shí)現(xiàn)epoll的調(diào)用。

最后,請(qǐng)?jiān)试S我吐槽一下Python的epoll相關(guān)文檔:簡(jiǎn)直太弱了?。?!必須看源碼才能弄清楚功能。

python異步有哪些方式

yield相當(dāng)于return,他將相應(yīng)的值返回給調(diào)用next()或者send()的調(diào)用者,從而交出了CPU使用權(quán),而當(dāng)調(diào)用者再次調(diào)用next()或者send()的時(shí)候,又會(huì)返回到y(tǒng)ield中斷的地方,如果send有參數(shù),還會(huì)將參數(shù)返回給yield賦值的變量,如果沒(méi)有就和next()一樣賦值為None。但是這里會(huì)遇到一個(gè)問(wèn)題,就是嵌套使用generator時(shí)外層的generator需要寫(xiě)大量代碼,看如下示例:?

注意以下代碼均在Python3.6上運(yùn)行調(diào)試

#!/usr/bin/env python# encoding:utf-8def inner_generator():

i = 0

while True:

i = yield i ? ? ? ?if i 10: ? ? ? ? ? ?raise StopIterationdef outer_generator():

print("do something before yield")

from_inner = 0

from_outer = 1

g = inner_generator()

g.send(None) ? ?while 1: ? ? ? ?try:

from_inner = g.send(from_outer)

from_outer = yield from_inner ? ? ? ?except StopIteration: ? ? ? ? ? ?breakdef main():

g = outer_generator()

g.send(None)

i = 0

while 1: ? ? ? ?try:

i = g.send(i + 1)

print(i) ? ? ? ?except StopIteration: ? ? ? ? ? ?breakif __name__ == '__main__':

main()1234567891011121314151617181920212223242526272829303132333435363738394041

為了簡(jiǎn)化,在Python3.3中引入了yield from

yield from

使用yield from有兩個(gè)好處,

1、可以將main中send的參數(shù)一直返回給最里層的generator,?

2、同時(shí)我們也不需要再使用while循環(huán)和send (), next()來(lái)進(jìn)行迭代。

我們可以將上邊的代碼修改如下:

def inner_generator():

i = 0

while True:

i = yield i ? ? ? ?if i 10: ? ? ? ? ? ?raise StopIterationdef outer_generator():

print("do something before coroutine start") ? ?yield from inner_generator()def main():

g = outer_generator()

g.send(None)

i = 0

while 1: ? ? ? ?try:

i = g.send(i + 1)

print(i) ? ? ? ?except StopIteration: ? ? ? ? ? ?breakif __name__ == '__main__':

main()1234567891011121314151617181920212223242526

執(zhí)行結(jié)果如下:

do something before coroutine start123456789101234567891011

這里inner_generator()中執(zhí)行的代碼片段我們實(shí)際就可以認(rèn)為是協(xié)程,所以總的來(lái)說(shuō)邏輯圖如下:?

接下來(lái)我們就看下究竟協(xié)程是啥樣子

協(xié)程coroutine

協(xié)程的概念應(yīng)該是從進(jìn)程和線(xiàn)程演變而來(lái)的,他們都是獨(dú)立的執(zhí)行一段代碼,但是不同是線(xiàn)程比進(jìn)程要輕量級(jí),協(xié)程比線(xiàn)程還要輕量級(jí)。多線(xiàn)程在同一個(gè)進(jìn)程中執(zhí)行,而協(xié)程通常也是在一個(gè)線(xiàn)程當(dāng)中執(zhí)行。它們的關(guān)系圖如下:

我們都知道Python由于GIL(Global Interpreter Lock)原因,其線(xiàn)程效率并不高,并且在*nix系統(tǒng)中,創(chuàng)建線(xiàn)程的開(kāi)銷(xiāo)并不比進(jìn)程小,因此在并發(fā)操作時(shí),多線(xiàn)程的效率還是受到了很大制約的。所以后來(lái)人們發(fā)現(xiàn)通過(guò)yield來(lái)中斷代碼片段的執(zhí)行,同時(shí)交出了cpu的使用權(quán),于是協(xié)程的概念產(chǎn)生了。在Python3.4正式引入了協(xié)程的概念,代碼示例如下:

import asyncio# Borrowed from countdown(number, n):

while n 0:

print('T-minus', n, '({})'.format(number)) ? ? ? ?yield from asyncio.sleep(1)

n -= 1loop = asyncio.get_event_loop()

tasks = [

asyncio.ensure_future(countdown("A", 2)),

asyncio.ensure_future(countdown("B", 3))]

loop.run_until_complete(asyncio.wait(tasks))

loop.close()12345678910111213141516

示例顯示了在Python3.4引入兩個(gè)重要概念協(xié)程和事件循環(huán),?

通過(guò)修飾符@asyncio.coroutine定義了一個(gè)協(xié)程,而通過(guò)event loop來(lái)執(zhí)行tasks中所有的協(xié)程任務(wù)。之后在Python3.5引入了新的async await語(yǔ)法,從而有了原生協(xié)程的概念。

async await

在Python3.5中,引入了ayncawait 語(yǔ)法結(jié)構(gòu),通過(guò)”aync def”可以定義一個(gè)協(xié)程代碼片段,作用類(lèi)似于Python3.4中的@asyncio.coroutine修飾符,而await則相當(dāng)于”yield from”。

先來(lái)看一段代碼,這個(gè)是我剛開(kāi)始使用asyncawait語(yǔ)法時(shí),寫(xiě)的一段小程序。

#!/usr/bin/env python# encoding:utf-8import asyncioimport requestsimport time

async def wait_download(url):

response = await requets.get(url)

print("get {} response complete.".format(url))

async def main():

start = time.time()

await asyncio.wait([

wait_download(""),

wait_download(""),

wait_download("")])

end = time.time()

print("Complete in {} seconds".format(end - start))

loop = asyncio.get_event_loop()

loop.run_until_complete(main())12345678910111213141516171819202122232425

這里會(huì)收到這樣的報(bào)錯(cuò):

Task exception was never retrieved

future: Task finished coro=wait_download() done, defined at asynctest.py:9 exception=TypeError("object Response can't be used in 'await' expression",)

Traceback (most recent call last):

File "asynctest.py", line 10, in wait_download

data = await requests.get(url)

TypeError: object Response can't be used in 'await' expression123456

這是由于requests.get()函數(shù)返回的Response對(duì)象不能用于await表達(dá)式,可是如果不能用于await,還怎么樣來(lái)實(shí)現(xiàn)異步呢??

原來(lái)Python的await表達(dá)式是類(lèi)似于”yield from”的東西,但是await會(huì)去做參數(shù)檢查,它要求await表達(dá)式中的對(duì)象必須是awaitable的,那啥是awaitable呢? awaitable對(duì)象必須滿(mǎn)足如下條件中其中之一:

1、A native coroutine object returned from a native coroutine function .

原生協(xié)程對(duì)象

2、A generator-based coroutine object returned from a function decorated with types.coroutine() .

types.coroutine()修飾的基于生成器的協(xié)程對(duì)象,注意不是Python3.4中asyncio.coroutine

3、An object with an await method returning an iterator.

實(shí)現(xiàn)了await method,并在其中返回了iterator的對(duì)象

根據(jù)這些條件定義,我們可以修改代碼如下:

#!/usr/bin/env python# encoding:utf-8import asyncioimport requestsimport time

async def download(url): # 通過(guò)async def定義的函數(shù)是原生的協(xié)程對(duì)象

response = requests.get(url)

print(response.text)

async def wait_download(url):

await download(url) # 這里download(url)就是一個(gè)原生的協(xié)程對(duì)象

print("get {} data complete.".format(url))

async def main():

start = time.time()

await asyncio.wait([

wait_download(""),

wait_download(""),

wait_download("")])

end = time.time()

print("Complete in {} seconds".format(end - start))

loop = asyncio.get_event_loop()

loop.run_until_complete(main())123456789101112131415161718192021222324252627282930

好了現(xiàn)在一個(gè)真正的實(shí)現(xiàn)了異步編程的小程序終于誕生了。?

而目前更牛逼的異步是使用uvloop或者pyuv,這兩個(gè)最新的Python庫(kù)都是libuv實(shí)現(xiàn)的,可以提供更加高效的event loop。

uvloop和pyuv

pyuv實(shí)現(xiàn)了Python2.x和3.x,但是該項(xiàng)目在github上已經(jīng)許久沒(méi)有更新了,不知道是否還有人在維護(hù)。?

uvloop只實(shí)現(xiàn)了3.x, 但是該項(xiàng)目在github上始終活躍。

它們的使用也非常簡(jiǎn)單,以u(píng)vloop為例,只需要添加以下代碼就可以了

import asyncioimport uvloop

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())123

理解python異步機(jī)制

最重要的是生成器函數(shù)碰到y(tǒng)ield停止執(zhí)行,收到next或send才會(huì)繼續(xù)執(zhí)行的機(jī)制。

而且send方法令我們可以傳遞值到生成器暫停的地方。

生成器執(zhí)行結(jié)束拋出 StopIteration 異常。

yield from用于把其他生成器當(dāng)做子例程調(diào)用。

然后它可以被其他用 async def 定義的的協(xié)程函數(shù)B和C await ,只有當(dāng) await 返回時(shí),B和C才繼續(xù)執(zhí)行。

這樣我們就可以有效地控制B和C的執(zhí)行順序。

然后我們創(chuàng)建了一個(gè)調(diào)度器,它對(duì)列表進(jìn)行了兩次深拷貝以避免問(wèn)題。它循環(huán)協(xié)程隊(duì)列,使用 send 方法對(duì)每個(gè)協(xié)程依次遞進(jìn),如果有協(xié)程已經(jīng)完成則將其移出隊(duì)列,當(dāng)列表中的協(xié)程全部完成時(shí)結(jié)束。

然后通過(guò) args=coro.send(None) 與該函數(shù)碰撞,得到含有 delay 參數(shù)的字典作為 send 的返回值。便可以判斷出是否調(diào)用調(diào)度器的睡眠機(jī)制。

最后在調(diào)度器中實(shí)現(xiàn)每一次協(xié)程列表循環(huán)結(jié)束后判斷在睡眠列表中的協(xié)程是否有到時(shí)間的,到時(shí)間或時(shí)間超出則添加到運(yùn)行協(xié)程列表中進(jìn)入循環(huán)執(zhí)行。如果運(yùn)行列表中的協(xié)程都執(zhí)行完了,則查看睡眠列表中的協(xié)程中還需睡眠的最少時(shí)間,線(xiàn)程睡眠,睡眠完成再將其添加到運(yùn)行隊(duì)列。

該裝飾器能將一個(gè)比較耗時(shí)的計(jì)算函數(shù)封裝為一個(gè)協(xié)程,使其可以被其他協(xié)程 await 。在調(diào)度器中利用 send 函數(shù)的返回值可以獲取它的類(lèi)型為 background 、函數(shù)入口地址以及函數(shù)的傳參,然后在調(diào)度器中按相應(yīng)機(jī)制執(zhí)行。

第二部分 是在調(diào)度器中的修改:我們讓調(diào)度器類(lèi)擁有了一個(gè)私有的 concurrent.futures.ThreadPoolExecutor() 對(duì)象。并在運(yùn)行協(xié)程隊(duì)列的循環(huán)判斷中將 background 類(lèi)型的操作提交給線(xiàn)程池對(duì)象,并將當(dāng)前的協(xié)程移出運(yùn)行隊(duì)列,添加到 futures 隊(duì)列中。然后在每次運(yùn)行隊(duì)列循環(huán)后判斷 futures 中的任務(wù)是否有完成的(使用的參數(shù)為一旦有任一任務(wù)完成或被取消都返回),如果主線(xiàn)程此時(shí)處于將要睡眠的狀態(tài),就等待相應(yīng)的時(shí)間,沒(méi)有的話(huà)則立刻返回,下次再查詢(xún),完成的任務(wù)將其所在協(xié)程帶入運(yùn)行隊(duì)列,任務(wù)結(jié)果通過(guò)調(diào)度器 send 傳回該協(xié)程。

Python異步編程4:協(xié)程函數(shù),協(xié)程對(duì)象,await關(guān)鍵字

協(xié)程函數(shù):async def?函數(shù)名。3.5+

協(xié)程對(duì)象:執(zhí)行協(xié)程函數(shù)()得到的協(xié)程對(duì)象。

3.5之后的寫(xiě)法:

3.7之后的寫(xiě)法:更簡(jiǎn)便

await后面?跟?可等待的對(duì)象。(協(xié)程對(duì)象,F(xiàn)uture,Task對(duì)象?約等于IO等待)

await實(shí)例2:串行執(zhí)行。 一個(gè)協(xié)程函數(shù)里面可以支持多個(gè)await ,雖然會(huì)串行,但是如果有其他協(xié)程函數(shù),任務(wù)列表也在執(zhí)行,依然會(huì)切換。只是案例中的main對(duì)應(yīng)執(zhí)行的others1和others2串行 。 await會(huì)等待對(duì)象的值得到之后才繼續(xù)往下走。


分享題目:python轉(zhuǎn)化異步函數(shù) python 異步
URL網(wǎng)址:http://weahome.cn/article/dogceec.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部