亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

試圖用一個事件停止循環,但它沒有

試圖用一個事件停止循環,但它沒有

慕村9548890 2021-06-06 16:35:07
據我所知,asyncio這應該只打印 0 到 4,但它會顯示完整的 10 位數字。stop_loop協程不應該在我點擊 5 后停止等待事件并取消循環嗎?import asyncioasync def run():    for i in range(10):        if i == 5:            e.set()        print(i)async def stop_loop():    await e.wait()    l.stop()e = asyncio.Event()l = asyncio.get_event_loop()l.set_debug(True)l.create_task(stop_loop())l.create_task(run())try:    l.run_forever()finally:    l.close()輸出是machine:programs user$ python3 conditional_stop.py 0123456789
查看完整描述

1 回答

?
MM們

TA貢獻1886條經驗 獲得超2個贊

asyncio通過在作為協程實現的任務之間切換來工作。一個協同程序是一個合作的程序,在協程自愿放棄控制權曾經在一段時間,以讓該asyncio事件循環切換到另一個任務。這與線程不同,在線程中每個任務可以并且將被調度程序“隨意”中斷。


并且協程每次await在另一個協程上使用時都會放棄控制,通常是在涉及某些 I/O 的地方。I/O 很慢,asyncio事件循環負責監控 I/O 流的變化,以便它可以知道哪些任務準備好再次做更多的工作。


你的問題是你有一個不合作的協程:


async def run():

    for i in range(10):

        if i == 5:

            e.set()

        print(i)

該例程沒有await語句,因此它永遠不會放棄對事件循環的控制。不能運行其他協程。


你可以等待一個asyncio.sleep()電話:


async def run():

    for i in range(10):

        if i == 5:

            e.set()

        print(i)

        await asyncio.sleep(0.01)  # wait 1/100th of a second

另一種選擇是將print(i)調用(這是一個 I/O 操作)替換為使用非阻塞輸出流的調用。如果您不在 Windows 上,則可StreamWriter以為以下對象創建異步 I/O 包裝器sys.stdout:


import os

import sys


async def run():

    # create an async writer for sys.stdout

    loop = asyncio.get_event_loop()

    writer_transport, writer_protocol = await loop.connect_write_pipe(

        asyncio.streams.FlowControlMixin, os.fdopen(sys.stdout.fileno(), 'wb'))

    writer = asyncio.streams.StreamWriter(

        writer_transport, writer_protocol, None, loop)


    for i in range(10):

        if i == 5:

            e.set()

        writer.write(b'%d\n' % i)

        await writer.drain()

不幸的是,尚不支持為 Windows 控制臺流創建異步 I/O 流,請參閱Pyton 問題 #26832,您必須改用線程池執行程序。


請注意,甚至與后者協同程序,也不能保證該stop協程將實際運行不久后,足以e.set()被稱為取消run()它讀取前10名!在處理之后,循環可以自由地將控制權交還給同一個協程await writer.drain()。向sys.stdout流緩沖區寫入短行很快,唯一要做.drain()的就是讓寫入協程有時間刷新內部傳輸緩沖區;sys.stdout大多數情況下直接非阻塞寫入成功,這并不總是有足夠的空間stop_loop()來跳入,run()協程會將其所有行都寫入寫入器傳輸。



查看完整回答
反對 回復 2021-06-16
  • 1 回答
  • 0 關注
  • 194 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號