Discuss / Python / 几点提醒或者小结

几点提醒或者小结

Topic source

Rainsho

#1 Created at ... [Delete] [Delete and Lock User]
grant select, insert, update, delete on awesome.* to 'www-data'@'localhost' identified by 'www-data';

这里通过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对象的操作已经完成,数据已经保存进数据库里面了,如果没有强迫症的话功能似乎已经实现了)

loop = asyncio.get_event_loop()
loop.run_until_complete(test())
loop.close()

5)暂时还没找到不报错的方法,还有太多要学。

LetItGo_宋

#2 Created at ... [Delete] [Delete and Lock User]

这个报错问题好像是因为没有关闭aiosql connection。我在SO上看见有人问类似问题。需要在关闭loop之前关闭这个,不知道廖大能去看看这个问题么

Buddha_6

#3 Created at ... [Delete] [Delete and Lock User]

对的,总结的很到位。支持!

Buddha_6

#4 Created at ... [Delete] [Delete and Lock User]

我一开始 也用的是 async 和 await, 不过我把 orm.py app.py 里的全改成 @asyncio.coroutine修饰 和 yield from 了,然后 test() 不用 @asyncio.coroutine修饰,第三个错误就没有了。 建议楼主可以试试。

Buddha_6

#5 Created at ... [Delete] [Delete and Lock User]
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()

CashQQJ

#6 Created at ... [Delete] [Delete and Lock User]

这里老师的代码有点小问题,在手动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

Reply