【问题标题】:Class variable is NoneType even though attribute was defined即使定义了属性,类变量也是 NoneType
【发布时间】:2021-01-15 01:02:55
【问题描述】:

我有一个如下所示的课程:

class DatabaseTest:

    def __init__(self):

        self.headers = {
            "host": os.environ["HOST"],
            "username": os.environ["USERNAME"],
            "password": os.environ["PASSWORD"]
        }

        self.db = None
        self.cursor = None
        asyncio.create_task(self._connect())

    
    async def _connect(self):
        
        self.db = await aiomysql.connect(self.headers['host'], self.headers['username'], self.headers['password'])
        self.cursor = await self.db.cursor()
        await self.cursor.execute('use bot')


    
    async def _insertData(self, guildid):

        sql = f'insert into data(guild) values ({guildid})'

        await self.cursor.execute(sql)

每当我执行await DatabaseTest()._insertData(123456789) 时,当我清楚地重新定义_connect 中的self.cursor 时,它会给出一个错误提示self.cursor 是NoneType。我知道调用 _connect 是因为我在最后放置了一个打印语句并打印了它。我该如何解决这个问题?

回溯是这样的(我将它用于不和谐的机器人):

Traceback (most recent call last):
  File "C:\Users\Name\PycharmProjects\compscibot\venv\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
    ret = await coro(*args, **kwargs)
  File "C:\Users\Name\PycharmProjects\compscibot\cogs\startup\Help.py", line 57, in cmdchannel
    channelid = await DatabaseTest().getData(ctx.guild.id,'cmdchannel')
  File "C:\Users\Name\PycharmProjects\compscibot\cogs\dbtest.py", line 75, in getData
    await self.cursor.execute(sql)
AttributeError: 'NoneType' object has no attribute 'execute'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\Name\PycharmProjects\compscibot\venv\lib\site-packages\discord\ext\commands\bot.py", line 903, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Users\Name\PycharmProjects\compscibot\venv\lib\site-packages\discord\ext\commands\core.py", line 859, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "C:\Users\Name\PycharmProjects\compscibot\venv\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'NoneType' object has no attribute 'execute'
None

【问题讨论】:

  • 能否提供具体的错误回溯?
  • 您是先拨打_connect() 并确保在_insertData 之前等待它吗?您是否检查了您的 _connect 并验证了 db.cursor() 是否返回光标?
  • 我认为_connect 从未被处决过。
  • @CATboardBETA 添加了问题的回溯
  • @GinoMempin 不应该 init 调用 _connect() 方法吗?

标签: python async-await python-asyncio aio-mysql


【解决方案1】:

直到await 才会切换上下文。

asyncio.create_task() 只是安排执行。

使用asyncio.sleep()

db = DatabaseTest()
await asyncio.sleep(0)
db._insertData(123456789)

或重构:

class DatabaseTest:
   def __init__(self):
        self.headers = {
            "host": os.environ["HOST"],
            "username": os.environ["USERNAME"],
            "password": os.environ["PASSWORD"]
        }

    async def __aenter__(self):
        await self._connect()
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        # cleanup
        await self.cursor.close()
        self.db.close()

    ...
async with DatabaseTest() as db:
    await db._insertData(123456789)

【讨论】:

  • 重构方法创造了奇迹。非常感谢京民!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多