簡體   English   中英

Python Asyncio/Await:無法理解 await 在循環中的作用

[英]Python Asyncio/Await: Having Trouble understanding the effect of await within a loop

代碼塊 B來自我正在嘗試跟隨的 Asyncio/Aiohttp教程視頻

快速說明:

The async function (The "coroutine") loops through a list of ticker symbols making API call requests for each symbol.

代碼塊 B

# GETTING MARKET DATA via API REQUESTS

######  SETUP STUFF  ######
api_key =  os.getenv('ALPHAVANTAGE_API_KEY')
url = 'https://www.alphavantage.co/query?function=OVERVIEW&symbol={}&apikey={}'

symbols = ['AAPL' , 'GOOG', 'TSLA', 'MSFT', 'AAPL' , 'DWAC' , 'VAXX' , 'MRNA' , 'JNJ']
results = []
######  SETUP STUFF  ######



async def get_symbols_async():
    ##########################
    session = aiohttp.ClientSession()
    for symbol in symbols:
        print('Working on:   {}'.format(symbol))
        CR = session.get(url.format(symbol, api_key), ssl=False)
        # CR:       Creates/Is a Coroutine function & does nothing by itself.
        response = await CR
        # AWAIT:    Throws Coroutine in the EVENT LOOP, where they can then run/ be executed.
        #           ... where Coroutines can MAKE & RETURN Calls.
    await session.close()
    ##########################


asyncio.run(get_symbols_async())

他說: at the end of each iteration within the for loop, the main program/thread has to wait for the response.

代碼塊A中的await沒有阻止/暫停下一行打印的執行。

##################### 問題

我看到的是一個內置的threading.join()等效機制在這里發揮作用。 我只是不知道它為什么或從哪里來,因為我不知道事件循環的內部工作原理。

我認為關鍵字await將協同程序放入事件循環中,然后在其中排隊/安排運行/執行,即發送任何 I/O 調用。 起初我認為這是一個誤導性的關鍵字,因為 await 語句啟動協程,其中響應悄悄地存儲在其分配的變量中(變量:在這種情況下為“response”)而不中斷 main,除非 main 之前需要返回值它准備好了。 那么掛斷點具體在哪里呢?

為什么主線程在每次 for 循環迭代結束時受到影響/停止(根據視頻中的人的說法)?

##################### 問題

代碼塊 A

async def greet():
    ##########################
    print('welcome')
    await asyncio.sleep(1)
    print('Hello')
    ##########################

asyncio.run(greet())

似乎在不阻止主程序的情況下將協程傳遞到事件循環中。

await 關鍵字后面的 object 不一定是協程,但它可以是任何可等待的object。協程是可等待的對象,但還有其他對象,例如asyncio.Future 的確,等待協程是使其開始執行的一種方式,但我認為說 await 因此是一個誤導性的術語是不公平的。 在所有情況下,它都按其暗示的方式進行:它等待可等待的 object 進入其“完成”state。如果它正在等待協程,則代碼不會繼續,直到協程完成執行並變為“完成”。 在 await 表達式等待時,其他任務有機會運行。 如果 awaitable 已經完成並且沒有其他任務准備好運行,則幾乎沒有延遲。

在您的代碼塊 A 中,asyncio.sleep(1) 返回協程 object,它什么都不做,但不會“完成”1 秒。 所以任務暫停一秒鍾。

你說視頻說,“在 for 循環中的每次迭代結束時,主程序/線程必須等待響應。” 是的,它將等待CR變為“完成”。 什么是鉻? 需要多長時間才能“完成”? 如果 CR 是一個簡單的 web 交易的結果,它可能只需要幾毫秒就可以完成。 那仍然是“等待回應”,但不容易看到。 您可以像這樣測量延遲:

t0 = time.time()
response = await CR
print(time.time() - t0)

您將看到等待的時間,以秒為單位。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM