為什么在Python異步編程中,ws.send_text("1") 會在 load_dataset("beans") 之前執行?

為什么在Python異步編程中,ws.send_text("1") 會在 load_dataset("beans") 之前執行?

python異步編程:函數執行順序詳解

在使用Python進行異步編程,特別是結合fastapiwebsocket時,理解函數執行順序至關重要。本文分析一個常見誤解:ws.send_text(“1”) 為什么看起來需要等待load_dataset(“beans”)完成才能執行?

代碼示例及誤解:

以下代碼片段演示了這個問題:

from fastapi import FastAPI, WebSocket from datasets import load_dataset from datetime import datetime  app = FastAPI()  @app.websocket("/ws") async def h(ws: WebSocket):     await ws.accept()     await ws.send_text(f"1: {datetime.now()}")  # 似乎等待load_dataset完成?     dataset = load_dataset("beans")     await ws.send_text(f"2: {datetime.now()}")

很多人誤以為ws.send_text(“1”)必須等待load_dataset(“beans”)加載完成后才會執行。

立即學習Python免費學習筆記(深入)”;

真相與實驗:

為了驗證,我們加入時間戳,并添加一個簡單的html頁面用于接收WebSocket消息:

<!DOCTYPE html> <html> <head>     <title>Chat</title>     <h1>WebSocket Chat</h1> </head> <body>     <ul id="messages"></ul>     <form id="sendMessageForm" onsubmit="sendMessage(event)">         <input type="text" id="messageText">         <button type="submit">Send</button>     </form>     <script>         var ws = new WebSocket("ws://localhost:8081/ws");         ws.onmessage = function(event) {             var messages = document.getElementById('messages')             var message = document.createElement('li')             var content = document.createTextNode(event.data)             message.appendChild(content)             messages.appendChild(message)         };         function sendMessage(event) {             var input = document.getElementById("messageText")             ws.send(input.value)             input.value = ''             event.preventDefault()         }     </script> </body> </html>

運行后,你會發現瀏覽器首先接收到”1: [時間戳]”,服務器日志隨后顯示load_dataset(“beans”)正在執行。這證明ws.send_text(“1”)的執行并不依賴于load_dataset(“beans”)的完成。

原因分析:

await ws.send_text(“1”)是異步操作,它將消息發送到WebSocket連接后立即返回,不會阻塞后續代碼的執行。load_dataset(“beans”)是一個耗時操作,但它也是異步執行的。 雖然load_dataset(“beans”)執行時間較長,但它不會阻塞ws.send_text(“1”)以及后續的ws.send_text(“2”),只是ws.send_text(“2”)的執行時間會被延遲。

因此,ws.send_text(“1”)在load_dataset(“beans”)之前發送,但由于load_dataset(“beans”)的耗時特性,”2: [時間戳]”的發送會被延遲。 這解釋了為什么瀏覽器先看到”1″,而服務器日志顯示數據加載仍在進行中。

以上就是

? 版權聲明
THE END
喜歡就支持一下吧
點贊9 分享