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

Discord机器人inv命令执行报错:TypeError: 'NoneType'对象不可迭代问题求助

TypeError: 'NoneType' object is not iterable in Discord Bot Inventory Command

Let's break down exactly what's causing this error and walk through how to fix it properly.

What's Going Wrong?

  1. Empty database records return None: When a user hasn't collected any animals or tools yet, your SELECT queries return None (since there's no matching row in the database). Your code tries to iterate over this None value with itertools.zip_longest, which throws the TypeError because None isn't an iterable.
  2. Unsafe SQL practices: Using f-strings to plug user IDs into your SQL queries is a critical security flaw—this leaves you wide open to SQL injection attacks.
  3. Unmanaged database resources: If an error occurs mid-execution, your current code might leave database connections or cursors open, which can cause issues down the line.

Fixed Code & Key Improvements

Here's the revised version of your inv command, with all issues addressed:

import itertools
import sqlite3
import lightbulb
import hikari

@plugin.command 
@lightbulb.command('inv', "player inventory", aliases=['inventory']) 
@lightbulb.implements(lightbulb.PrefixCommand) 
async def inv(ctx: lightbulb.context): 
    animal_list = [None,"力Fox", "🐺Wolf", "🐱Cat", "劣Raccoon", "🐯Tiger", "女Lion", "🐆Leopard","歷Deer", "煉Zebra", "濾Unicorn"] 
    tools_list = [None, "🔫Rifle", "🎣Rod", "⛏Pick"] 

    # Use with statements to auto-handle database connections/cursors (no leaks!)
    with sqlite3.connect("eco.sqlite") as db:
        with db.cursor() as cursor:
            # Parameterized query to avoid SQL injection (never use f-strings here!)
            cursor.execute('SELECT * FROM animals WHERE user_id = ?', (ctx.author.id,)) 
            # Fallback to empty tuple if no record exists (avoids None iteration)
            animals = cursor.fetchone() or ()  
            cursor.execute('SELECT * FROM tools WHERE user_id = ?', (ctx.author.id,)) 
            tools = cursor.fetchone() or ()  

    # Filter valid entries, and handle None values from zip_longest
    animals_ = [f"{i} x{j}" for i, j in itertools.zip_longest(animal_list, animals) 
                if j is not None and 0 < j < 2] 
    tools_ = [f"{i} x{j}" for i, j in itertools.zip_longest(tools_list, tools) 
              if j is not None and 0 < j < 2] 

    # Format empty inventory messages cleanly
    animals_ = "\n".join(animals_) if animals_ else "***No animals in Inventory***" 
    tools_ = "\n".join(tools_) if tools_ else "***No tools in Inventory***" 

    emb = hikari.Embed(title="Inventory", description="All your collected stuff", colour="#50a45c") 
    emb.add_field(name="Animals", value=animals_) 
    emb.add_field(name="Tools", value=tools_) 
    await ctx.respond(embed=emb)

Key Fixes Explained:

  • None fallback: cursor.fetchone() or () ensures we always get an iterable (even if there's no database record), so zip_longest doesn't throw an error.
  • Parameterized SQL: Using ? placeholders and passing the user ID as a tuple eliminates SQL injection risks—this is the only safe way to include user input in queries.
  • Auto-managed resources: The with statements automatically close connections and cursors when the block finishes, even if an error occurs. The database also commits changes automatically if no exceptions are raised, so we don't need manual commit() calls.
  • j is not None check: Prevents errors when zip_longest fills gaps with None (if your animal_list and database row lengths don't match).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 17:17:38