You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

B3(BigBrotherBot) Python2.7 MySQL查询报错:Cursor无fetchone属性

地图评分插件查询错误修复方案

问题现象

调用!maprating命令时触发错误,日志输出如下:

230205 14:19:09 DEBUG    'AdminPlugin: handle command !maprating'
230205 14:19:09 VERBOSE  "RCON sending (127.0.0.1:27960) 'tell 0 ^3: ^8[pm]^7 ^7There was an error processing your command'"
230205 14:19:09 ERROR    "Handler AdminPlugin could not handle event Say: AttributeError: 'Cursor' object has no attribute 'fetchone'

问题分析

B3 Bot框架封装的Cursor对象并非标准Python MySQLdb游标,它没有fetchone()方法。查看插件内其他数据库操作代码(如is_rated方法),框架提供的正确单行数据获取方法是getRow()。

修复代码

修改cmd_maprating方法,将cursor.fetchone()替换为cursor.getRow():

def cmd_maprating(self, data, client, cmd=None):
    map_name = self.console.game.mapName
    query = "SELECT map_name, SUM(rating) AS total_rating FROM mapratings WHERE map_name = %s GROUP BY map_name"
    cursor = self.console.storage.query(query, (map_name,))
    if cursor.rowcount == 0:
        client.message("No ratings for map %s" % map_name)
    else:
        result = cursor.getRow()
        client.message("Map %s has a total rating of %d" % (result['map_name'], result['total_rating']))

完整修复后插件代码

import os
import sys
import b3
import b3.events
import b3.plugin


class MapratingPlugin(b3.plugin.Plugin):
    def onLoadConfig(self):
        self.rated_players = {}
        self.map_ratings = {}
    def onStartup(self):
        self.registerEvent(b3.events.EVT_CLIENT_SAY)

        self._adminPlugin = self.console.getPlugin('admin')
        if self._adminPlugin:
            self._adminPlugin.registerCommand(self, 'rategood', 0, self.cmd_rategood)
            self._adminPlugin.registerCommand(self, 'ratebad', 0, self.cmd_ratebad)
            self._adminPlugin.registerCommand(self, 'maprating', 0, self.cmd_maprating)

    def is_rated(self, client, map_name):
        cursor = self.console.storage.query("""            SELECT rating FROM mapratings WHERE guid = %s AND map_name = %s        """, (client.guid, map_name))
        
        if cursor.rowcount:
            return (True, cursor.getRow()['rating'])
        else:
            return (False, 0)

    def add_rating(self, client, map_name, rating):
        self.console.storage.query("""            INSERT INTO mapratings (guid, player_name, map_name, rating)            VALUES (%s, %s, %s, %s)        """, (client.guid, client.name, map_name, rating))

    def update_rating(self, client, map_name, rating):
        self.console.storage.query("""            UPDATE mapratings SET rating = %s WHERE guid = %s AND map_name = %s        """, (rating, client.guid, map_name))

    def cmd_rategood(self, data, client, cmd=None):
        map_name = self.console.game.mapName
        (is_rated, existing_rating) = self.is_rated(client, map_name)
        rating = 1
        if is_rated:
            if existing_rating == rating:
                client.message('You have already rated this map as good')
            else:
                self.update_rating(client, map_name, rating)
                client.message('Map %s rated as good by you' % map_name)
        else:
            self.add_rating(client, map_name, rating)
            client.message('Map %s rated as good by you' % map_name)

    def cmd_ratebad(self, data, client, cmd=None):
        map_name = self.console.game.mapName
        (is_rated, existing_rating) = self.is_rated(client, map_name)
        rating = -1
        if is_rated:
            if existing_rating == rating:
                client.message('You have already rated this map as bad')
            else:
                self.update_rating(client, map_name, rating)
                client.message('Map %s rated as bad by you' % map_name)
        else:
            self.add_rating(client, map_name, rating)
            client.message('Map %s rated as bad by you' % map_name)

    def cmd_maprating(self, data, client, cmd=None):
        map_name = self.console.game.mapName
        query = "SELECT map_name, SUM(rating) AS total_rating FROM mapratings WHERE map_name = %s GROUP BY map_name"
        cursor = self.console.storage.query(query, (map_name,))
        if cursor.rowcount == 0:
            client.message("No ratings for map %s" % map_name)
        else:
            result = cursor.getRow()
            client.message("Map %s has a total rating of %d" % (result['map_name'], result['total_rating']))

内容的提问来源于stack exchange,提问作者Juli199696

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 16:16:06