# 前言

之前尝试用 python 的 telethon 开发时,由于不太了解 python 遇到不少坑
幸运的是通过 Google 从前人哪里找到了解决办法
其中一个问题让我影响深刻,为了弄清楚为什么,我又回头了解 asyncio eventLoop
这个过程让我更加了解 python

# RuntimeError: There is no current event loop in thread 'Thread-1'.

意思是线程中没有当前事件循环
字我都认识,但是组合起来后,没看懂什么意思
不过幸好找到了解决办法,加上下面的两行代码就行,顺利解决了
不过虽然解决了,但我还是不知道为什么,于是便抽空仔细阅读了关于 asyncio 的内容

new_loop = asyncio.new_event_loop()
asyncio.set_event_loop(new_loop)

# 参考地址

  • https://blog.csdn.net/u013421629/article/details/100163014 (解决办法)
  • https://stackoverflow.com/questions/51311383/python-flask-with-telethon (里面说和 asyncio 有关)
  • https://blog.csdn.net/qq_34341423/article/details/102874263 (eventLoop 的使用)

# 探究过程

之前有看到关于 EventLoop 的介绍,但是没心思看下去
自己遇到的了问题,才有探究的动力
于是我试着通过代码了解它

# 首先写一段代码 简单了解 asyncio eventLoop

文件名 test.py

import asyncio
async def coroutine_example():
    await asyncio.sleep(3)
    print('task')
if __name__ == '__main__':
    coro = coroutine_example()
    loop = asyncio.get_event_loop()
    loop.run_until_complete(coro)
    loop.close()

async await 很熟悉的异步语法糖
测试过程中发现 必须加入 run_until_complete 才能执行,直接执行就会提示错误

# 在线程 (thread) 中执行 EventLoop

在阅读文章时,看到这么一句话
get_event_loop () 只会在主线程帮您创建新的 event loop,而在其他线程中调用 get_event_loop () 则会报错
结合之前遇到的问题,所以是因为在线程中执行 EventLoop,引发了错误
写了个简单的关于线程代码,并调用 EventLoop
通过注释,新建 eventLoop 部分代码,验证了非主线程没有 EventLoop
python3.7 以后 asyncio.run (coroutine_example ()) 就能代替上面 4 行代码的效果

文件名 thread.py

import asyncio
import time
from threading import Thread
from test import coroutine_example
def func(name):
    print(f"{name}开始")
    time.sleep(0.5)
    print(f"{name}结束")
    
    #新建 eventLoop
    new_loop = asyncio.new_event_loop()
    asyncio.set_event_loop(new_loop)
    
    #执行异步方法
    loop = asyncio.get_event_loop()
    loop.run_until_complete(coroutine_example())
    # asyncio.run(coroutine_example())
 
if __name__ == '__main__':
    t1 = Thread(target=func, args=("线程1",))
    t2 = Thread(target=func, args=("线程2",))
    t1.start()
    t2.start()
    print("主线程结束")

# 个人理解总结

python async 异步 需要通过 loop.run_until_complete 启动
默认主线程有 eventLoop,可以直接 get_event_loop
其他线程执行 async 异步,需要新创建 eventLoop, new_event_loop 后才能获取 get_event_loop,不然会提示错误
python3.7 以后, asyncio.run 以更简洁代码的启动 async