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

导出字典到CSV时遇TypeError:列表不支持格式字符串传递

Python支出追踪器CSV功能报错修复:TypeError: unsupported format string passed to list.format

错误原因分析

  1. 价格格式化错误:self._data字典中值为列表类型(如"Water": [24]),但fill_table方法中直接用f"{price:.2f}"对列表做浮点数格式化,列表不支持该操作,触发TypeError。
  2. CSV写入逻辑问题:使用csv.DictWriter时,传入的fieldnames是self._data的键,但writerow(self._data)会直接写入列表值,导致CSV内容不符合预期;同时export按钮错误绑定了clear_table函数,完全未实现导出功能。
  3. 次要错误:add_element方法中的错误提示文字逻辑矛盾,"That is not an invalid input"应为"That is not a valid input"。

修复步骤

1. 修正数据结构

将self._data中的列表值改为单个数值(每个支出条目仅对应一个价格):

self._data = {"Water": 24, 
              "Rent": 1000, 
              "Coffee": 30,
              "Grocery": 300, 
              "Phone": 45, 
              "Internet": 70}

2. 修复CSV初始写入逻辑

替换初始化中的CSV写入代码,确保表头和数据正确写入:

with open("aib_october.csv", 'w', newline='') as file:
    fieldnames = ["Description", "Price"]
    writer = csv.DictWriter(file, fieldnames=fieldnames)
    writer.writeheader()
    for desc, price in self._data.items():
        writer.writerow({"Description": desc, "Price": price})

3. 添加正确的CSV导出函数

新增导出函数,并修正export按钮的信号绑定:

@Slot()
def export_to_csv(self):
    with open("expenses_export.csv", 'w', newline='') as file:
        writer = csv.writer(file)
        writer.writerow(["Description", "Price"])
        for row in range(self.table.rowCount()):
            desc = self.table.item(row, 0).text()
            price = self.table.item(row, 1).text()
            writer.writerow([desc, price])
    print("数据已成功导出到expenses_export.csv")

在__init__方法中修改按钮绑定:

self.export.clicked.connect(self.export_to_csv)

4. 修正错误提示文字

在add_element方法中,将错误提示改为:

print("That is not a valid input:", price, "Make sure to enter a price!")

修复后完整代码

import csv
import sys
from PySide6.QtCore import Qt, Slot
from PySide6.QtGui import QAction , QPainter
from PySide6.QtWidgets import (QApplication, QHeaderView, QHBoxLayout, QLabel, QLineEdit, 
                               QMainWindow, QPushButton, QTableWidget, QTableWidgetItem, QVBoxLayout, 
                               QWidget)
from PySide6.QtCharts import QChartView, QPieSeries, QChart

class Widget(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.items = 0
        # 修正数据结构:值为单个数值而非列表
        self._data = {"Water": 24, 
                      "Rent": 1000, 
                      "Coffee": 30,
                      "Grocery": 300, 
                      "Phone": 45, 
                      "Internet": 70}
        # 修正CSV初始写入逻辑
        with open("aib_october.csv", 'w', newline='') as file:
            fieldnames = ["Description", "Price"]
            writer = csv.DictWriter(file, fieldnames=fieldnames)
            writer.writeheader()
            for desc, price in self._data.items():
                writer.writerow({"Description": desc, "Price": price})
        # Left Widget
        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(["Description", "Price"])
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        # Chart
        self.chart_view = QChartView()
        self.chart_view.setRenderHint(QPainter.Antialiasing)

        # Right Widget
        self.description = QLineEdit()
        self.price = QLineEdit()
        self.add = QPushButton("Add")
        self.clear = QPushButton("Clear")
        self.quit = QPushButton("Quit")
        self.plot = QPushButton("Plot")
        self.export = QPushButton("export")

        # Disabling 'Add' button
        self.add.setEnabled(False)

        self.right = QVBoxLayout()
        self.right.addWidget(QLabel("Description"))
        self.right.addWidget(self.description)
        self.right.addWidget(QLabel("Price"))
        self.right.addWidget(self.price)
        self.right.addWidget(self.add)
        self.right.addWidget(self.plot)
        self.right.addWidget(self.chart_view)
        self.right.addWidget(self.export)
        self.right.addWidget(self.clear)
        self.right.addWidget(self.quit)

        # QWidget Layout
        self.layout = QHBoxLayout()

        self.layout.addWidget(self.table)
        self.layout.addLayout(self.right)

        # Set the layout to the QWidget
        self.setLayout(self.layout)

        # Signals and Slots
        self.add.clicked.connect(self.add_element)
        self.quit.clicked.connect(self.quit_application)
        self.plot.clicked.connect(self.plot_data)
        self.clear.clicked.connect(self.clear_table)
        # 修正export按钮绑定
        self.export.clicked.connect(self.export_to_csv)
        self.description.textChanged[str].connect(self.check_disable)
        self.price.textChanged[str].connect(self.check_disable)

        # Fill example data
        self.fill_table()

    @Slot()
    def add_element(self):
        des = self.description.text()
        price = self.price.text()

        try:
            price_item = QTableWidgetItem(f"{float(price):.2f}")
            price_item.setTextAlignment(Qt.AlignRight)

            self.table.insertRow(self.items)
            description_item = QTableWidgetItem(des)

            self.table.setItem(self.items, 0, description_item)
            self.table.setItem(self.items, 1, price_item)

            self.description.setText("")
            self.price.setText("")

            self.items += 1
        except ValueError:
            # 修正错误提示文字
            print("That is not a valid input:", price, "Make sure to enter a price!")

    @Slot()
    def check_disable(self, x):
        if not self.description.text() or not self.price.text():
            self.add.setEnabled(False)
        else:
            self.add.setEnabled(True)

    @Slot()
    def plot_data(self):
        # Get table information
        series = QPieSeries()
        for i in range(self.table.rowCount()):
            text = self.table.item(i, 0).text()
            number = float(self.table.item(i, 1).text())
            series.append(text, number)

        chart = QChart()
        chart.addSeries(series)
        chart.legend().setAlignment(Qt.AlignLeft)
        self.chart_view.setChart(chart)

    @Slot()
    def quit_application(self):
        QApplication.quit()

    def fill_table(self, data=None):
        data = self._data if not data else data
        for desc, price in data.items():
            description_item = QTableWidgetItem(desc)
            # 现在price是单个数值,格式化正常
            price_item = QTableWidgetItem(f"{price:.2f}")
            price_item.setTextAlignment(Qt.AlignRight)
            self.table.insertRow(self.items)
            self.table.setItem(self.items, 0, description_item)
            self.table.setItem(self.items, 1, price_item)
            self.items += 1

    @Slot()
    def clear_table(self):
        self.table.setRowCount(0)
        self.items = 0

    # 新增CSV导出函数
    @Slot()
    def export_to_csv(self):
        with open("expenses_export.csv", 'w', newline='') as file:
            writer = csv.writer(file)
            writer.writerow(["Description", "Price"])
            for row in range(self.table.rowCount()):
                desc = self.table.item(row, 0).text()
                price = self.table.item(row, 1).text()
                writer.writerow([desc, price])
        print("数据已成功导出到expenses_export.csv")

class MainWindow(QMainWindow):
    def __init__(self, widget):
        QMainWindow.__init__(self)
        self.setWindowTitle("The pynancial advisor")

        # Menu
        self.menu = self.menuBar()
        self.file_menu = self.menu.addMenu("File")

        # Exit QAction
        exit_action = QAction("Exit", self)
        exit_action.setShortcut("Ctrl+Q")
        exit_action.triggered.connect(self.exit_app)

        self.file_menu.addAction(exit_action)
        self.setCentralWidget(widget)

    @Slot()
    def exit_app(self, checked):
        QApplication.quit()

if __name__ == "__main__":
    # Qt Application
    app = QApplication(sys.argv)
    # QWidget
    widget = Widget()
    # QMainWindow using QWidget as central widget
    window = MainWindow(widget)
    window.resize(800, 600)
    window.show()

    # Execute application
    sys.exit(app.exec())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 02:21:03