使用Motor驱动连接MongoDB到discord.py机器人

0 投票
1 回答
32 浏览
提问于 2025-04-12 20:06

我正在尝试把一个MongoDB数据库连接到我的discord.py机器人,用来存储管理、用户和日志数据。我对这方面还很陌生,现在遇到了一些问题,关闭连接时总是出现“对象NoneType不能在'await'表达式中使用”的错误,尽管调试时打印的内容显示它并不是NoneType。

所有提到的函数、类和类对象/方法都是已经定义的,只是为了简洁起见省略了;如果需要,我可以提供更多的源代码。

相关的源代码:

import discord
import motor.motor_asyncio
from discord import app_commands
from pymongo.server_api import ServerApi


class DB_handler():
  uri = f'mongodb+srv://ALIXIC_AI:{secret("DB_PASSWORD")}@cluster-1.pw8s6xw.mongodb.net/?retryWrites=true&w=majority&appName=Cluster-1'

  @classmethod
  async def connect(cls):
    motor_client = motor.motor_asyncio.AsyncIOMotorClient(cls.uri, server_api=ServerApi('1'))
    try:
      await motor_client.admin.command('ping')
      conn_message = await style_format("Successfully connected to database\n", "green")
      await Utils.console_message("CONN", conn_message, "CONN")
      print(motor_client)
      return motor_client
    except Exception as e:
      e = str(e)
      conn_message = await style_format(f"Failed to connect to database: {await length_format(e)}\n")
      await Utils.console_message("CONN", conn_message, "CONN")

  @classmethod
  async def close(cls,
                  motor_client):
    if motor_client is not None:
      try:
        await motor_client.close()
        conn_message = await style_format("Safely disconnected from database\n", "green")
        await Utils.console_message("CONN", conn_message, "CONN")
      except Exception as e:
        e = str(e)
        conn_message = await style_format(f"Error while closing database connection: {await length_format(e)}", "red")
        await Utils.console_message("CONN", conn_message, "CONN")
        print()
    else:
      conn_message = await style_format("No active database connection present.\n", "red")
      await Utils.console_message("CONN", conn_message, "CONN")
      print()


@client.tree.command(name = "db_test",
                     description = "DEBUG COMMAND - Developer command to test the database connection")
@app_commands.describe()
async def db_test(interaction: discord.Interaction):
  if not await permission_check(Permissions.development, interaction.user.roles): #pyright: ignore
    message = f"You are not permitted to run this command {interaction.user.mention}"
    await Responses.handler(interaction, message)
  else:
    message = f"Testing database connection - Triggered by {interaction.user.mention}\nSee console for details"
    await Responses.handler(interaction, message)
    db_client = await DB_handler.connect()
    print(db_client)
    print(type(db_client))
    await DB_handler.close(db_client)

控制台输出:

2024-03-25 13:47:34 INFO     discord.client logging in using static token
2024-03-25 13:47:35 INFO     discord.gateway Shard ID None has connected to Gateway (Session ID: ff5948aeb2fa50ff7e9f8e4e3c2a394a).

2024-03-25 13:47:37 CONN     Alixic AI - Alixic#0320 successfully has connected to [AX] Alixic Incorporated

2024-03-25 13:47:37 ACTN     Uptime tracking started

2024-03-25 13:47:38  CMD     db_test
UID:  ##################     (@iigibbyz)
CID: 1142244524656173106     (#staff-comms)
2024-03-25 13:47:38 RESP     Testing database connection - Triggered by <@##################>
                             See console for details

2024-03-25 13:47:39 CONN     Successfully connected to database

AsyncIOMotorClient(MongoClient(host=['ac-cbuun0h-shard-00-02.pw8s6xw.mongodb.net:27017', 'ac-cbuun0h-shard-00-00.pw8s6xw.mongodb.net:27017', 'ac-cbuun0h-shard-00-01.pw8s6xw.mongodb.net:27017'], document_class=dict, tz_aware=False, connect=False, retrywrites=True, w='majority', appname='Cluster-1', authsource='admin', replicaset='atlas-37pqcs-shard-0', tls=True, server_api=<pymongo.server_api.ServerApi object at 0x7b0519d92170>, driver=DriverInfo(name='Motor', version='3.3.2', platform='asyncio')))
AsyncIOMotorClient(MongoClient(host=['ac-cbuun0h-shard-00-02.pw8s6xw.mongodb.net:27017', 'ac-cbuun0h-shard-00-00.pw8s6xw.mongodb.net:27017', 'ac-cbuun0h-shard-00-01.pw8s6xw.mongodb.net:27017'], document_class=dict, tz_aware=False, connect=False, retrywrites=True, w='majority', appname='Cluster-1', authsource='admin', replicaset='atlas-37pqcs-shard-0', tls=True, server_api=<pymongo.server_api.ServerApi object at 0x7b0519d92170>, driver=DriverInfo(name='Motor', version='3.3.2', platform='asyncio')))
<class 'motor.motor_asyncio.AsyncIOMotorClient'>
2024-03-25 13:47:39 CONN     Error while closing database connection: ["object NoneType can't be used in 'await'
                             expression"]

我修改了连接和关闭的类方法,试图处理或避免出现NoneType,但都没有成功。因为我还是新手,所以不知道接下来该怎么做。

1 个回答

0

在你的情况下,motor_client 是一个 AsyncIOMotorClient,正如 pymongo 的文档 中提到的那样,AsyncIOMotorClient.close 是一个普通的函数,而不是一个协程。所以当你写 await motor_client.close() 时,代码首先会执行 motor_client.close(),这个函数会返回 None,然后再去等待 None,这样就会报错。因此,只需要把 await motor_client.close() 这一行中的 await 去掉,就能解决你的问题。

撰写回答