最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python使用asyncio標(biāo)準(zhǔn)庫(kù)對(duì)異步IO的支持

 更新時(shí)間:2023年11月04日 15:19:51   投稿:yin  
Python中,所有程序的執(zhí)行都是單線程的,但可同時(shí)執(zhí)行多個(gè)任務(wù),不同的任務(wù)被時(shí)間循環(huán)(Event Loop)控制及調(diào)度,Asyncio是Python并發(fā)編程的一種實(shí)現(xiàn)方式;是Python 3.4版本引入的標(biāo)準(zhǔn)庫(kù),直接內(nèi)置了對(duì)異步IO的支持

Python中,所有程序的執(zhí)行都是單線程的,但可同時(shí)執(zhí)行多個(gè)任務(wù),不同的任務(wù)被時(shí)間循環(huán)(Event Loop)控制及調(diào)度,Asyncio是Python并發(fā)編程的一種實(shí)現(xiàn)方式;是Python 3.4版本引入的標(biāo)準(zhǔn)庫(kù),直接內(nèi)置了對(duì)異步IO的支持。

異步IO

CPU的速度遠(yuǎn)遠(yuǎn)快于磁盤(pán)、網(wǎng)絡(luò)等IO。在一個(gè)線程中,CPU執(zhí)行代碼的速度極快,然而,一旦遇到IO操作,如讀寫(xiě)文件、發(fā)送網(wǎng)絡(luò)數(shù)據(jù)時(shí),就需要等待IO操作完成,才能繼續(xù)進(jìn)行下一步操作。這種情況稱為同步IO。

在IO操作的過(guò)程中,當(dāng)前線程被掛起,而其他需要CPU執(zhí)行的代碼就無(wú)法被當(dāng)前線程執(zhí)行了。

因?yàn)橐粋€(gè)IO操作就阻塞了當(dāng)前線程,導(dǎo)致其他代碼無(wú)法執(zhí)行,所以我們必須使用多線程或者多進(jìn)程來(lái)并發(fā)執(zhí)行代碼,為多個(gè)用戶服務(wù)。每個(gè)用戶都會(huì)分配一個(gè)線程,如果遇到IO導(dǎo)致線程被掛起,其他用戶的線程不受影響。

多線程和多進(jìn)程的模型雖然解決了并發(fā)問(wèn)題,但是系統(tǒng)不能無(wú)上限地增加線程。由于系統(tǒng)切換線程的開(kāi)銷也很大,所以,一旦線程數(shù)量過(guò)多,CPU的時(shí)間就花在線程切換上了,真正運(yùn)行代碼的時(shí)間就少了,結(jié)果導(dǎo)致性能嚴(yán)重下降。

由于我們要解決的問(wèn)題是CPU高速執(zhí)行能力和IO設(shè)備的龜速嚴(yán)重不匹配,多線程和多進(jìn)程只是解決這一問(wèn)題的一種方法。

另一種解決IO問(wèn)題的方法是異步IO。當(dāng)代碼需要執(zhí)行一個(gè)耗時(shí)的IO操作時(shí),它只發(fā)出IO指令,并不等待IO結(jié)果,然后就去執(zhí)行其他代碼了。一段時(shí)間后,當(dāng)IO返回結(jié)果時(shí),再通知CPU進(jìn)行處理。

asyncio

asyncio是Python 3.4版本引入的標(biāo)準(zhǔn)庫(kù),直接內(nèi)置了對(duì)異步IO的支持。

asyncio的編程模型就是一個(gè)消息循環(huán)。我們從asyncio模塊中直接獲取一個(gè)EventLoop的引用,然后把需要執(zhí)行的協(xié)程扔到EventLoop中執(zhí)行,就實(shí)現(xiàn)了異步IO。

asyncio實(shí)現(xiàn)Hello world代碼如下:

import asyncio

@asyncio.coroutine
def hello():
    print("Hello world!")
    # 異步調(diào)用asyncio.sleep(1):
    r = yield from asyncio.sleep(1)
    print("Hello again!")

# 獲取EventLoop:
loop = asyncio.get_event_loop()
# 執(zhí)行coroutine
loop.run_until_complete(hello())
loop.close()

@asyncio.coroutine把一個(gè)generator標(biāo)記為coroutine類型,然后,我們就把這個(gè)coroutine扔到EventLoop中執(zhí)行。

hello()會(huì)首先打印出Hello world!,然后,yield from語(yǔ)法可以讓我們方便地調(diào)用另一個(gè)generator。由于asyncio.sleep()也是一個(gè)coroutine,所以線程不會(huì)等待asyncio.sleep(),而是直接中斷并執(zhí)行下一個(gè)消息循環(huán)。當(dāng)asyncio.sleep()返回時(shí),線程就可以從yield from拿到返回值(此處是None),然后接著執(zhí)行下一行語(yǔ)句。

asyncio.sleep(1)看成是一個(gè)耗時(shí)1秒的IO操作,在此期間,主線程并未等待,而是去執(zhí)行EventLoop中其他可以執(zhí)行的coroutine了,因此可以實(shí)現(xiàn)并發(fā)執(zhí)行。

我們用Task封裝兩個(gè)coroutine試試:

import threading
import asyncio

@asyncio.coroutine
def hello():
    print('Hello world! (%s)' % threading.currentThread())
    yield from asyncio.sleep(1)
    print('Hello again! (%s)' % threading.currentThread())

loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

觀察執(zhí)行過(guò)程:

Hello world! (<_MainThread(MainThread, started 140735195337472)>)
Hello world! (<_MainThread(MainThread, started 140735195337472)>)
(暫停約1秒)
Hello again! (<_MainThread(MainThread, started 140735195337472)>)
Hello again! (<_MainThread(MainThread, started 140735195337472)>)

由打印的當(dāng)前線程名稱可以看出,兩個(gè)coroutine是由同一個(gè)線程并發(fā)執(zhí)行的。

如果把asyncio.sleep()換成真正的IO操作,則多個(gè)coroutine就可以由一個(gè)線程并發(fā)執(zhí)行。

我們用asyncio的異步網(wǎng)絡(luò)連接來(lái)獲取sina、sohu和163的網(wǎng)站首頁(yè):

import asyncio

@asyncio.coroutine
def wget(host):
    print('wget %s...' % host)
    connect = asyncio.open_connection(host, 80)
    reader, writer = yield from connect
    header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host
    writer.write(header.encode('utf-8'))
    yield from writer.drain()
    while True:
        line = yield from reader.readline()
        if line == b'\r\n':
            break
        print('%s header > %s' % (host, line.decode('utf-8').rstrip()))
    # Ignore the body, close the socket
    writer.close()

loop = asyncio.get_event_loop()
tasks = [wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

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

wget www.sohu.com...
wget www.sina.com.cn...
wget www.163.com...
(等待一段時(shí)間)
(打印出sohu的header)
www.sohu.com header > HTTP/1.1 200 OK
www.sohu.com header > Content-Type: text/html
...
(打印出sina的header)
www.sina.com.cn header > HTTP/1.1 200 OK
www.sina.com.cn header > Date: Wed, 20 May 2015 04:56:33 GMT
...
(打印出163的header)
www.163.com header > HTTP/1.0 302 Moved Temporarily
www.163.com header > Server: Cdn Cache Server V2.0
...

可見(jiàn)3個(gè)連接由一個(gè)線程通過(guò)coroutine并發(fā)完成。

小結(jié)

asyncio提供了完善的異步IO支持;異步操作需要在coroutine中通過(guò)yield from完成;多個(gè)coroutine可以封裝成一組Task然后并發(fā)執(zhí)行。

到此這篇關(guān)于Python使用asyncio標(biāo)準(zhǔn)庫(kù)對(duì)異步IO的支持的文章就介紹到這了,更多相關(guān)Python使用asyncio內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

郁南县| 安新县| 敦化市| 武川县| 北海市| 巴南区| 瑞安市| 望奎县| 习水县| 兴业县| 福建省| 东乌珠穆沁旗| 保定市| 临泉县| 中卫市| 聂拉木县| 札达县| 曲阜市| 天峻县| 仙桃市| 景洪市| 濉溪县| 丰都县| 黄骅市| 鸡西市| 达州市| 磴口县| 新建县| 中牟县| 巨野县| 宁阳县| 东平县| 顺昌县| 黎平县| 饶阳县| 隆尧县| 玛纳斯县| 普洱| 饶阳县| 紫云| 临夏县|