我正在编写一个类,并希望在__init__
方法中使用异步函数来设置类所需的一些变量。问题是,我不能这样做,因为__init__
必须是同步的。
这是我的代码的相关部分(为简单起见编辑,逻辑保持不变):
# This has to be called outside of the class
asyncDatabaseConnection = startDBConnection()
class discordBot(discord.Client):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Init is only run once, but we cant use async stuff here
self.firstRun = True
async def on_ready(self):
# Other stuff happens here but it doesen't involve this question
# on_ready is called when bot is ready, but can be called multiple times when running
# (if bot has to reconnect to API), so we have to check
if self.firstRun:
await asyncDatabaseConnection.setValue("key", "value")
self.firstRun = False
if __name__ == "__main__":
# Instance class and start async stuff
bot = discordBot()
bot.run()
正如你所看到的,它适用于Discord机器人,但这并不重要,它更多的是关于逻辑。
我想要调用的函数是asyncDatabaseConnection.setValue("key", "value")
。
就像我说的那样,我不能从__init__
调用它,因为__init__
必须是同步的,所以我在init调用期间将firstRun
设置为True
,然后我可以稍后使用它来判断代码是否已经运行过
on_ready
是一个在机器人准备开始发送/接收数据时调用的函数,因此我可以将它用作第二个__init__
。问题来自于on_ready
在整个程序运行过程中可以多次调用的事实,这意味着我必须进行之前描述的firstRun
检查。
这似乎是很多代码只是为了在启动时做一件事(以及增加开销,无论多么小,当调用on_ready
时)。这样做有更干净的方法吗?
这有点尴尬,但你可以create a Task
,然后运行它并得到它的结果。如果经常这样做,可能有助于编写辅助函数:
def run_and_get(coro):
task = asyncio.create_task(coro)
asyncio.get_running_loop().run_until_complete(task)
return task.result()
class discordBot(discord.Client):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
run_and_get(asyncDatabaseConnection.setValue("key", "value"))
这取决于有一个运行事件循环,我相信Client.__init__
设置