Python中如何解决廖雪峰教程Day 4编写Model时遇到的RuntimeError: Event loop is closed问题
纯小白,顺着廖雪峰的 python 教程往下走,好不容易走到实战 Day 4 - 编写 Model ,蛋疼连续剧开始了
蛋疼第一期:
#test.py(下面首行都没有缩进,不知道怎么缩进,先忽略不看)
import asyncio, orm
from models import User, Blog, Comment
loop = asyncio.get_event_loop()
async def test():
await orm.create_pool(loop=loop,host='localhost', port=3306,
user='www-data', password='www-data', database='awesome')
u = User(name='Test', email='[email protected]',
passwd='1234567890', image='about:blank')
await u.save()
loop.run_until_complete(test())
loop.close()
结果报错: RuntimeError: Event loop is closed
蛋疼第二期:参考评论建议,在 loop.close()后加入一个 sys.exit()语句
import asyncio, orm
from models import User, Blog, Comment
loop = asyncio.get_event_loop()
async def test():
await orm.create_pool(loop=loop,host='localhost', port=3306,
user='www-data', password='www-data', database='awesome')
u = User(name='Test', email='[email protected]',
passwd='1234567890', image='about:blank')
await u.save()
loop.run_until_complete(test())
loop.close()
#加入 sys.exit()语句
if loop.is_closed():
sys.exit(0)
结果报错: RuntimeError: Event loop is closed (并没有什么软用)
蛋疼第三期:
参考评论建议,在关闭 event loop 之前,首先需要关闭连接池,所以增加
了销毁连接池的方法
在 orm.py 中定义 destroy_pool()方法:
async def destroy_pool():
#声明全局变量
global __pool
#如果__pool 不为空
if __pool is not None:
#关闭__pool
__pool.close()
#异步调用__pool.wait_closed(), wait_closed()用于等待直到 close()方法完成
await __pool.wait_closed()
然后修改 test.py 代码:
import asyncio, orm
from models import User, Blog, Comment
loop = asyncio.get_event_loop()
async def test():
await orm.create_pool(loop=loop,host='localhost', port=3306,
user='www-data', password='www-data', database='awesome')
u = User(name='Test', email='[email protected]',
passwd='1234567890', image='about:blank')
await u.save()
await destroy_pool() #销毁连接池
loop.run_until_complete(test())
loop.close()
结果报错: timeError: Event loop is closed (看评论别人都解决了为何我还是蛋疼)
蛋疼第四期:询问朋友,朋友说看这里 http://stackoverflow.com/questions/32598231/asyncio-runtimeerror-event-loop-is-closed
结果报错: I don ’ t understand (英文和中文理解力都不够)
抱着在杭州找到一份 python 工作的目的,求 v 友解救,带我出坑,手动抱拳
还有,按照我目前的进度,想快速找到python工作还需要熟悉哪些模块?
Python中如何解决廖雪峰教程Day 4编写Model时遇到的RuntimeError: Event loop is closed问题
好歹你放个教程的链接啊
这个问题通常在使用异步数据库驱动(比如aiomysql)时,在Windows系统上运行异步代码后出现。根本原因是asyncio.run()执行完毕后会自动关闭事件循环,但某些异步驱动在后台可能仍有任务未完全清理,尝试在已关闭的循环上注册清理回调,从而触发这个错误。
解决方案是: 在程序入口点显式获取并管理事件循环,而不是依赖asyncio.run()的自动管理。同时,确保所有异步资源(如数据库连接池)在使用后被正确关闭。
下面是一个完整的、可运行的解决方案示例,它修改了app.py的启动方式:
# app.py
import asyncio
import logging
from aiohttp import web
from datetime import datetime
from models import Model
import orm
logging.basicConfig(level=logging.INFO)
# 你的路由处理函数(假设是异步的)
async def handle(request):
# 示例:创建一个Model实例并保存
# 这里假设你的Model有一个异步的save方法
# model_instance = Model(...)
# await model_instance.save()
return web.Response(text='Hello, World')
def init():
app = web.Application()
app.router.add_get('/', handle)
return app
# 修改后的主函数,显式管理事件循环
async def main():
# 1. 初始化数据库连接池(这是orm模块里应该做的事)
await orm.create_pool(loop=asyncio.get_event_loop(),
user='www-data',
password='www-data',
db='awesome',
host='localhost',
port=3306)
# 2. 初始化Web应用
app = init()
# 3. 启动Web服务器
runner = web.AppRunner(app)
await runner.setup()
site = web.TCPSite(runner, 'localhost', 9000)
await site.start()
print(f"Server started at http://localhost:9000")
# 保持服务器运行,直到收到终止信号
await asyncio.Event().wait()
if __name__ == '__main__':
# 关键修改:获取事件循环并运行main协程
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
except KeyboardInterrupt:
print("Server stopped")
finally:
# 可选:在这里执行一些同步的清理工作
# 但注意,此时事件循环可能已经停止,不要调用异步方法
loop.close()
核心改动说明:
main()改为异步函数:将所有初始化步骤(数据库连接、启动服务器)放入一个async main()函数。- 显式获取和管理事件循环:使用
asyncio.get_event_loop()获取循环,用loop.run_until_complete(main())运行主协程。 - 优雅关闭:通过捕获
KeyboardInterrupt(如Ctrl+C)来触发关闭,并在finally块中关闭循环。这给了程序一个明确的“终点”,让异步驱动有机会在循环关闭前完成清理。
另外,请检查你的orm.py中的create_pool函数,确保它接受loop参数并正确使用它来创建连接池。同时,在Model类的方法中,确保所有数据库操作都通过这个连接池进行。
一句话总结: 将启动方式从asyncio.run()改为显式管理事件循环,确保数据库连接池在事件循环关闭前被正确初始化和持有。
destroy_pool() 这个是你新定义的方法 还是 orm 定义的?
在 orm.py 中定义的 destroy_pool()方法:
async def destroy_pool():
global __pool
if __pool is not None:
__pool.close()
await __pool.wait_closed()
那你怎么在 test()调用 destroy_pool() 这个方法的
我在 save()之后调用 destroy_pool()方法的,就是销毁这个连接池
async def test():
await orm.create_pool(loop=loop,host=‘localhost’, port=3306,
user=‘www-data’, password=‘www-data’, database=‘awesome’)
u = User(name=‘Test’, email=’[email protected]’,
passwd=‘1234567890’, image=‘about:blank’)
await u.save()
await destroy_pool() #销毁连接池
什么意思,解释一下呗
前面那些内容要看一点吧 , 不能直接就看实战吧。
await orm.destroy_pool()
之前是看了,但是印象肯定不深的,只能回去补,主要是不知道是哪个知识点的问题,刚才这个使用模块不知道跟我这个坑哪里有关联
哈哈。同道中人啊。我也是看廖老师的网站学的 Python 。不过我知道把项目搭建起来并且测试几个 API 成功了,并没有把整个项目做完。你这个问题我是在教程的评论里找到答案的。你可以仔细看下下面的评论。
liaoxuefeng 的教程是可以评论的,直接把问题提给作者不行么?
我一直跟着教程走,然后到实战 day2 就蒙逼了。
就是按照评论里的方法来的,看着他们开心的说解决了然而我并没有,我深深怀疑起了我的代码。。
已评论,坐等解答了
我是自己注释+参考别人注释+参考评论+参考官方文档 葫芦吞枣下来的 也只是看个大概
重点要自己一步步注释上去,把一个个方法的用法看懂了,基本上意思就出来了 Day1 有个朋友给出了实战方法论回去再看看呗 别放弃啊 慢慢啃
你可以参考我写的。我最近是将廖雪峰这个博客重构,去除 VUE 和 JINJA 的渲 restful 一些。你要是感兴趣可以在 github 上搜索 FuckBlog 找到我们。
另外 就目前来看 应该没有比我注释更详细的了→_→ 对了 我很有些是参考墨灵这位仁兄的,对了,看到你们这些小菜鸡出 BUG 真开心哈哈哈哈(逃
看了你的代码,但是还是不知道问题出在哪里。菊花紧
实测,sys.exit(0) 可以的。
要是你不可以,是不是没引入。没引入会报错<br>Traceback (most recent call last):<br> File "./<a target="_blank" href="http://user.py" rel="nofollow noopener">user.py</a>", line 18, in <module><br> sys.exit(0)<br>NameError: name 'sys' is not defined<br><br>......<br>......<br><br>RuntimeError: Event loop is closed<br>
我第一次也只看最下面报错,忽略上面了。引入后就好了。
asyncio.set_event_loop(asyncio.new_event_loop())
asyncio.set_event_loop(loop)
尝试使用这 set_event_loop 再去关闭或者清空连接池
我就用第三期 销毁连接池的方法解决了这个问题啊。

