与烧瓶程序一起使用时出现 Asyncio 错误 "There is no current event loop in thread"

Asyncio error "There is no current event loop in thread" when using with a flask program

我正在制作一个控制 Microbit 并显示一些传感器数据的小网页。

我正在尝试根据我在前端单击的内容,通过我的 Flask 后端实现对 microbit 的异步读写。

但是当我使用 flask 来 运行 一个函数时,它给出了一个错误

  "There is no current event loop in thread"

函数如下所示。它初始化我用于异步串行通信的库。

import aioserial
import asyncio
import serial



def test1():
     return aioserial.AioSerial(port='COM5', baudrate = 115200)
     
print(test1())

当我运行这个文件时,输出符合预期

AioSerial<id=0x1c5a373ed90, open=True>(port='COM5', baudrate=115200, bytesize=8, parity='N', 
stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)

然而,当我从 flask 函数调用相同的函数时

@app.before_first_request
def startserial():
    global aioserialinstance
    try:
        portaddress = find_comport(PID_MICROBIT, VID_MICROBIT, 115200)
        print(portaddress)
        aioserialinstance = test1()

except Exception as e:
    print(str(e))
    print("device not connected or wrong port number")

我收到这个错误

  File "C:\Users\adity\Documents\Brbytes Folder\lessons-interactive21\Flask-microbit\app.py", line 23, in startserial
    aioserialinstance = aioserial.AioSerial(port='COM5', baudrate = 115200)
  File "C:\Users\adity\Documents\Brbytes Folder\lessons-interactive21\Flask-microbit\venv\Lib\site-packages\aioserial\aioserial.py", line 57, in __init__
    self._read_lock: asyncio.Lock = asyncio.Lock()
  File "C:\Users\adity\AppData\Local\Programs\Python\Python39\Lib\asyncio\locks.py", line 81, in __init__
    self._loop = events.get_event_loop()
  File "C:\Users\adity\AppData\Local\Programs\Python\Python39\Lib\asyncio\events.py", line 642, in get_event_loop
    raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-2'.

当我使用 Flask 应用 运行 时,我不确定是什么导致了这个错误。当我制作一些测试程序并阅读时,编写的一切都很完美,但是在将这些函数导入烧瓶时 app.py 会因这个错误而中断它们。

我对 asyncio 了解不多,完全没有办法解决这个问题。

报错说明不是MainThread中没有事件循环,对于Python中的异步程序我们通常在MainThread中只有一个asyncio循环,我们不想要更多asyncio 循环,因为它们会互相争抢时间,整个应用程序会变慢并且更容易出错。

如果我是你,我会使用 aiohttp 或任何其他异步 http 框架而不是 Flask,否则使用任何其他非异步库 serial port

但是,如果需要的话,如何在非 MainThread 中获得另一个循环?请查找示例:

import asyncio
from threading import Thread, current_thread


async def async_job():
    await asyncio.sleep(5)
    print(f"{current_thread().getName()}___Hurray!\n")


def asyncio_wrapper_function():
    try:
        loop = asyncio.get_event_loop()
    except RuntimeError as ex:
        print(ex)
        loop = asyncio.new_event_loop()
    try:
        loop.run_until_complete(async_job())
    finally:
        loop.close()


if __name__ == '__main__':
    ths = [
        Thread(target=asyncio_wrapper_function, name=f"Th-{i}") for i in range(4)
    ]
    [i.start() for i in ths]
    [i.join() for i in ths]

    print("All work done!")