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

使用Asciimatics开发购物应用遇too many values to unpack错误求助

解决Asciimatics ListBox的"too many values to unpack"错误

这个错误的根源很明确:Asciimatics的ListBox组件要求选项是二元组格式,也就是(显示文本, 对应值),但你直接把SQLite返回的完整行对象(包含多个字段)传递给了ListBox,导致组件尝试解包时无法匹配预期的2个值。

具体修复步骤

1. 修正ListBox的选项格式

在你的Shop类中,需要把数据库返回的商品记录转换成ListBox能识别的二元组。我们可以把商品名称+价格作为显示文本,商品ID作为对应的值(方便后续操作数据库):

修改Shop类的__init__和loadContent方法:

def __init__(self, screen, db):
    super(Shop, self).__init__(screen, screen.height * 2 // 3, screen.width * 2 // 3, on_load=self.loadContent, hover_focus=True, title="Obchod ~~ ASCIIMATICO ~~")
    self.model = db
    # 初始化时就传入格式化后的选项
    formatted_products = [(f"{row['product']} - {row['price']}€", row['id']) for row in db.showAllProducts()]
    self.productsList = ListBox(Widget.FILL_FRAME, formatted_products, name="shop")
    # ... 其余代码保持不变

def loadContent(self):
    # 重新加载时也要格式化选项
    formatted_products = [(f"{row['product']} - {row['price']}€", row['id']) for row in self.model.showAllProducts()]
    self.productsList.options = formatted_products

2. 修正购物车添加逻辑

你的addToCart方法里有两个错误:引用了不存在的self._model和错误的字段名contacts(你的ListBox name是shop)。修改成这样:

def addToCart(self):
    selected_id = self.data["shop"]
    if selected_id is not None:
        self.model.addToCart(selected_id)
        # 重新加载商品列表,确保界面更新
        self.loadContent()

3. 修复SQL注入风险(可选但推荐)

你的ShopDB类中,用字符串拼接SQL语句存在安全隐患,改成参数化查询:

def addToCart(self, product_id):
    self.db.cursor().execute('''UPDATE products SET in_cart=1 WHERE id=?''', (product_id,))
    self.db.commit()

def removeFromCart(self, product_id):
    self.db.cursor().execute('''UPDATE products SET in_cart=0 WHERE id=?''', (product_id,))
    self.db.commit()

完整修改后的代码

from asciimatics.widgets import Frame, ListBox, Layout, Divider, Text, \
Button, TextBox, Widget
from asciimatics.scene import Scene
from asciimatics.screen import Screen
from asciimatics.exceptions import ResizeScreenError, NextScene, StopApplication
import sys
import sqlite3

class ShopDB(object):
    def __init__(self):
        # vytvorí databazu v RAM pamati
        self.db = sqlite3.connect(':memory:')
        self.db.row_factory = sqlite3.Row
        self.db.cursor().execute('''
        CREATE TABLE products(
        id INTEGER PRIMARY KEY,
        product TEXT,
        price REAL,
        notes TEXT,
        in_cart INTEGER)
        ''')
        self.db.cursor().execute('''INSERT INTO products(id, product, price, notes, in_cart) VALUES(1, "Mlieko", 0.59, "Veľmi lahodné plnotučné kravské mlieko.",0 )''')
        self.db.cursor().execute('''INSERT INTO products(id, product, price, notes, in_cart) VALUES(2, "Maslo", 1.59, "Kvalitné maslo priamo z vidieka.",0 )''')
        self.db.cursor().execute('''INSERT INTO products(id, product, price, notes, in_cart) VALUES(3, "Chlieb", 1.19, "Čerstvý chlieb.",0 )''')
        self.db.cursor().execute('''INSERT INTO products(id, product, price, notes, in_cart) VALUES(4, "Med", 3.49, "Veľký pohár medu.",0 )''')
        self.db.cursor().execute('''INSERT INTO products(id, product, price, notes, in_cart) VALUES(5, "Jablko", 0.49, "Zdravé jabĺčko.",0 )''')
        self.db.cursor().execute('''INSERT INTO products(id, product, price, notes, in_cart) VALUES(6, "Zemiaky 5kg", 0.60, "Vrecko zemiakov.",0 )''')
        self.db.cursor().execute('''INSERT INTO products(id, product, price, notes, in_cart) VALUES(7, "Šiška", 0.99, "Čerstvá a mäkká šiška.",0 )''')
        self.db.cursor().execute('''INSERT INTO products(id, product, price, notes, in_cart) VALUES(8, "Soľ", 0.29, "Soľ nad zlato.",0 )''')
        self.db.cursor().execute('''INSERT INTO products(id, product, price, notes, in_cart) VALUES(9, "Cukor", 1.19, "Kryštálový cukor.",0 )''')
        self.db.commit()

    def addToCart(self, product_id):
        self.db.cursor().execute('''UPDATE products SET in_cart=1 WHERE id=?''', (product_id,))
        self.db.commit()

    def removeFromCart(self, product_id):
        self.db.cursor().execute('''UPDATE products SET in_cart=0 WHERE id=?''', (product_id,))
        self.db.commit()

    def showAllProducts(self):
        return self.db.cursor().execute('''SELECT * FROM products''').fetchall()

    def showCart(self):
        return self.db.cursor().execute('''SELECT * FROM products WHERE in_cart=1''').fetchall()

class Shop(Frame):
    def __init__(self, screen, db):
        super(Shop, self).__init__(screen, screen.height * 2 // 3, screen.width * 2 // 3, on_load=self.loadContent, hover_focus=True, title="Obchod ~~ ASCIIMATICO ~~")
        self.model = db
        # 格式化ListBox选项为(显示文本, 商品ID)
        formatted_products = [(f"{row['product']} - {row['price']}€", row['id']) for row in db.showAllProducts()]
        self.productsList = ListBox(Widget.FILL_FRAME, formatted_products, name="shop")
        self.addButton = Button("Pridaj do košíka", self.addToCart)
        #self.deleteButton = Button("Odstráň z košíka", self.deleteFromCart)
        self.showCartButton = Button("Ukáž košík", self.showCart)

        listLayout = Layout([100], fill_frame=True)
        self.add_layout(listLayout)
        listLayout.add_widget(self.productsList)
        listLayout.add_widget(Divider())

        buttonLayout = Layout([1,1,1,1])
        self.add_layout(buttonLayout)
        buttonLayout.add_widget(self.addButton, 0)
        buttonLayout.add_widget(self.showCartButton, 3)

        self.fix()

    def loadContent(self):
        # 重新加载时也要格式化选项
        formatted_products = [(f"{row['product']} - {row['price']}€", row['id']) for row in self.model.showAllProducts()]
        self.productsList.options = formatted_products

    def addToCart(self):
        selected_id = self.data["shop"]
        if selected_id is not None:
            self.model.addToCart(selected_id)
            # 重新加载商品列表,更新界面
            self.loadContent()

    def showCart(self):
        self.save()
        raise NextScene("Cart")

#class Cart(Frame):
#class ProductDetails(Frame):
def demo(screen, scene):
    scenes = [
        Scene([Shop(screen, database)], -1, name="Shop")
    ]
    screen.play(scenes, stop_on_resize=True, start_scene=scene)

database = ShopDB()
last_scene = None
while True:
    try:
        Screen.wrapper(demo, catch_interrupt=True, arguments=[last_scene])
        sys.exit(0)
    except ResizeScreenError as e:
        last_scene = e.scene

现在运行代码应该就能正常显示商品列表,并且可以点击按钮添加商品到购物车了。后续你可以继续完善Cart类,用同样的方式处理购物车商品的ListBox选项。

内容的提问来源于stack exchange,提问作者Martin Kumecký

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:57:39