asyncio 错误地警告流对象被垃圾收集;显式调用“stream.close()”

AKH*_*HEW 5 python python-3.x async-await python-asyncio aio-mysql

我正在使用 python3.8 的内置 asyncio 包和已安装的 aiomysql 包实现异步 MySQL 查询执行。即使我已经正确关闭了所有打开的游标和连接,我的控制台上仍然会出现如下错误消息。

An open stream object is being garbage collected; call "stream.close()" explicitly.
Run Code Online (Sandbox Code Playgroud)

下面给出了代码的摘要......

#db.py

import asyncio

class AsyncMysqlSession:

    def __init__(self, loop, db_settings=DEFAULTDB):
        self.db_settings = db_settings
        self.loop = loop

    async def __aenter__(self):
        self.conn = await aiomysql.connect(host=self.db_settings['HOST'],
                                       port=self.db_settings['PORT'],
                                       user=self.db_settings['USER'],
                                       password=self.db_settings['PASSWORD'],
                                       db=self.db_settings['NAME'],
                                       loop=self.loop)
        self.cursor = await self.conn.cursor(aiomysql.cursors.DictCursor)
        return self

    async def __aexit__(self, exception, value, traceback):
        await self.cursor.close()
        self.conn.close()

    async def query(self, sql, *args):
        await self.cursor.execute(sql, values)
        await self.conn.commit()
        rows = await self.cursor.fetchall()
        return list(rows)


async def aiomysql_query(sql, *args):
    """
    Mysql asynchronous connection wrapper
    """
    loop = asyncio.get_event_loop()
    async with AsyncMysqlSession(loop) as mysql:
        db_result = await mysql.query(sql, *args)
        return db_result
Run Code Online (Sandbox Code Playgroud)

aiomysql_query 被导入到另一个文件中

#views.py

 import asyncio
 .....
 

 async def main():
     .....
     .....
     
     await aiomysql_query(sql1, *args1)
     await aiomysql_query(sql2, *args2)

 .....

 asyncio.run(main())

 ....
Run Code Online (Sandbox Code Playgroud)

我在这里做错了什么(?)还是错误地显示了错误信息?。任何解决此问题的线索将不胜感激...... TIA !

pyg*_*eek 1

看来您可能只是忘记关闭事件循环\xe2\x80\x94in 除了await conn.wait_closed()@VPfB 上面建议的。

\n

手动使用较低级别的方法调用(例如asyncio.get_event_loop(). 具体来说,self.loop.close()必须调用。

\n
#db.py\n\nimport asyncio\n\nclass AsyncMysqlSession:\n\n    def __init__(self, loop, db_settings=DEFAULTDB):\n        self.db_settings = db_settings\n        self.loop = loop\n\n    async def __aenter__(self):\n        self.conn = await aiomysql.connect(host=self.db_settings[\'HOST\'],\n                                       port=self.db_settings[\'PORT\'],\n                                       user=self.db_settings[\'USER\'],\n                                       password=self.db_settings[\'PASSWORD\'],\n                                       db=self.db_settings[\'NAME\'],\n                                       loop=self.loop)\n        self.cursor = await self.conn.cursor(aiomysql.cursors.DictCursor)\n        return self\n\n    async def __aexit__(self, exception, value, traceback):\n        await self.cursor.close()\n        self.conn.close()\n        self.loop.close()\n\n    async def query(self, sql, *args):\n        await self.cursor.execute(sql, values)\n        await self.conn.commit()\n        rows = await self.cursor.fetchall()\n        return list(rows)\n\n\nasync def aiomysql_query(sql, *args):\n    """\n    Mysql asynchronous connection wrapper\n    """\n    loop = asyncio.get_event_loop()\n    async with AsyncMysqlSession(loop) as mysql:\n        db_result = await mysql.query(sql, *args)\n        return db_result\n
Run Code Online (Sandbox Code Playgroud)\n

参考

\n

https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.shutdown_asyncgens

\n

https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.get_event_loop

\n