几点提醒或者小结
Topic source我一开始 也用的是 async 和 await, 不过我把 orm.py app.py 里的全改成 @asyncio.coroutine修饰 和 yield from 了,然后 test() 不用 @asyncio.coroutine修饰,第三个错误就没有了。 建议楼主可以试试。
def test(loop):
yield from orm.create_pool(loop=loop,user = 'www-data', password = 'www-data', database = 'awesome')
user = User(id='ni',name = 'Coco Shi',email = '23@kkk', passwd = '102033', image = 'blank')
yield from user.save()
loop = asyncio.get_event_loop()
loop.run_until_complete(test(loop))
loop.close()
这里老师的代码有点小问题,在手动ctrl-c退出的时候会报错,最后的提示信息是:“RuntimeError: Event loop is closed”。原因是退出loop的代码有bug,我看了aiohttp和aiomysql的文档后将代码改了一下。 将原来的初始化函数中创建服务的代码:
srv = await loop.create_server(app.make_handler(), '127.0.0.1', 9000)
拆开写:
handler = app.make_handler()
srv = await loop.create_server(handler, '127.0.0.1', 9000)
然后函数返回的时候返回一个字典,包含app、srv、handler三个实例对象:
rs = dict()
rs['app'] = app
rs['srv'] = srv
rs['handler'] = handler
return rs
原来的主程序改为接收返回的这个字典并且执行退出工作:
loop = asyncio.get_event_loop()
rs = loop.run_until_complete(init(loop))
try:
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
rs['srv'].close()
loop.run_until_complete(rs['srv'].wait_closed())
loop.run_until_complete(rs['app'].shutdown())
loop.run_until_complete(rs['handler'].finish_connections(60.0))
loop.run_until_complete(rs['app'].cleanup())
loop.close()
光执行这些还不够,服务程序退出时aiohttp不报错了,但是aiomysql还是会报错,原因是在退出loop时aiomysql的连接池没有正确关闭。 我们需要在loop退出时处理数据库连接池关闭事宜。这里需要用到aiohttp里的信号处理函数。 我们注册一个服务关闭时的处理函数,用来关闭数据库连接池。 首先在orm里添加一个数据库连接池关闭函数:
async def close_pool():
logging.info('close database connection pool...')
global __pool
__pool.close()
await __pool.wait_closed()
然后在app里添加一个自定义服务关闭信号处理函数,只需简单的调用以上函数即可:
async def on_close(app):
await myorm.close_pool()
最后在初始化函数中加入注册这个函数即可:
app.on_shutdown.append(on_close)
经过上面这些处理后,退出服务程序时控制台就不会显示出错信息了。
- 1
Rainsho
这里通过grant授权给了'www-data',所以可以,使用数据库awesome。(好吧,我一开始没反应过来)
直接使用廖老师操作对象的可能有以下潜在错误: 1)在create_pool的时候报错:没有参数loop; 2)加入loop或者loop=loop后报错:loop未定义; 3)加入@asyncio.coroutine修饰后(我是3.5的版本,用的async和await),报错:cannot 'yield from' a coroutine object in a non-coroutine generator 4)再加入下面部分后,报错:Event loop is closed(不过这个时候,上面user对象的操作已经完成,数据已经保存进数据库里面了,如果没有强迫症的话功能似乎已经实现了)
5)暂时还没找到不报错的方法,还有太多要学。