簡體   English   中英

RuntimeError:您不能在與異步事件循環相同的線程中使用 AsyncToSync

[英]RuntimeError: You cannot use AsyncToSync in the same thread as an async event loop

我正在使用燒瓶在 python 中制作儀表板。 它需要運行三個任務:flask、 datastream_handler()dashboard_handler() 其中一項任務datastream_handler()需要是異步函數。

我使用線程來允許任務同時運行,(flask 和dashboard_handler()是線程, datastream_handler()從主線程運行)。

dashboard_handler()datastream_handler()啟動並完美運行,flask 似乎啟動了,但是當我訪問網頁時,它在終端中給我一個錯誤: RuntimeError: You cannot use AsyncToSync in the same thread as an async event loop - just await the async function directly.

我很困惑,因為我直接等待異步函數(datastream_handler)?

我嘗試過切換它,以便 flask 是主線程,並且datastream_handler()作為 threading.Thread 啟動(使用 asyncio.run 從非異步函數啟動異步函數)。 但是,這只是給出了同樣的錯誤。

我查了這個錯誤,有幾個人在使用 Django 和 requests-html 時遇到了同樣的錯誤,但他們的發現是針對他們各自的框架的,不能應用於燒瓶。

這是我的代碼:

datastream_handlerdashboard_handler在不同的文件中; dashboard_handler只是一個帶有 while 循環的普通同步函數,而datastream_handler是一個異步函數,目前只包含一個帶有 print 和 asyncio.sleep 的 while 循環,用於測試目的。

我不認為這些函數的內容導致錯誤,但如果我錯了,請糾正我

app = Flask(__name__)
socket = SocketIO(app)

@app.route("/")
async def index():
    return render_template("index.html")

def start_flask():
    socket.run(app, host="0.0.0.0", port=5000)
        
async def main():

    q = Queue() #queue for data transfer
    threading.Thread(target=dashboard_handler, args=(q,), daemon=True).start()
    threading.Thread(target=start_flask, daemon=True).start()

    await datastream_handler(q)


if __name__ == "__main__":
    asyncio.run(main())

如果有人可以提供幫助,我將不勝感激

謝謝

Flask放入線程的原因是什么? Flask應用程序應該在主線程中啟動。

關於這個錯誤, RuntimeError: You cannot use AsyncToSync in the same thread as an async event loop - just await the async function directly.

我認為這來自兩個原因:

  1. 您正在線程中運行 Flask
  2. 您正在使用async def index()哪個燒瓶將使用asgiref的模塊AsyncToSync將其轉換為線程異步,並且無法在線程中完成。

如果您想使用線程同時運行其中的 3 個並且其中一個是asynchronous的,那么您可以使用python-worker鏈接

  1. datastream_handlerdashboard_handler定義為 worker
from worker import worker, async_worker

@async_worker
async def datastream_handler(q):
    ...

@worker
def dashboard_handler(q):
    ...
  1. 在您的主文件中:
if __name__ == "__main__":
    q = Queue()
    asyncio.run(datastream_handler(q))
    dashboard_handler(q)
    socket.run(app, host="0.0.0.0", port=5000)

datastream_handlerdashboard_handler將自動作為線程運行。

暫無
暫無

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

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