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?
- Empty database records return
None: When a user hasn't collected any animals or tools yet, yourSELECTqueries returnNone(since there's no matching row in the database). Your code tries to iterate over thisNonevalue withitertools.zip_longest, which throws theTypeErrorbecauseNoneisn't an iterable. - 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.
- 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:
Nonefallback:cursor.fetchone() or ()ensures we always get an iterable (even if there's no database record), sozip_longestdoesn'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
withstatements 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 manualcommit()calls. j is not Nonecheck: Prevents errors whenzip_longestfills gaps withNone(if youranimal_listand database row lengths don't match).
内容的提问来源于stack exchange,提问作者Pain.
相关产品推荐
相关产品推荐

