Tkinter+Sqlite3调用Entry.get()报NameError变量未定义错误
问题核心原因
你遇到的NameError: name 'earn' is not defined报错本质是变量作用域不匹配:earn、earning_value两个输入框控件是定义在earning()函数内部的局部变量,全局作用域下的submit()函数没有权限访问这两个变量,自然调用.get()时会提示名称不存在。
除了这个直接触发报错的问题,你的代码还有5处会导致运行异常的硬伤:
- 缩进不符合Python语法:
earning()函数内部的所有代码没有做缩进,Python靠缩进识别代码块归属,直接运行会先报语法错误 Entry控件的textvariable参数传值错误:该参数要求接收Tkinter提供的StringVar/DoubleVar类型变量,你直接传入字符串'earn'/'earning_value'没有任何实际作用- SQL插入语句字段数不匹配:你创建的
calculate表设置了5个非空字段,但插入语句只传了2个值,就算解决变量问题也会触发SQL字段数不匹配的报错 - 存在SQL注入风险:用f-string直接拼接用户输入到SQL语句中,只要输入内容包含单引号等特殊字符就会搞崩SQL语句,还存在数据泄露风险
- 数据库操作逻辑错误:事务提交方法属于数据库连接对象,不是游标对象,你写的
c.commit()本身就无法正常执行;另外操作完成后只关闭了游标,没有关闭数据库连接,会导致连接泄漏。
修复后可直接运行的代码
from tkinter import * from tkinter import ttk import sqlite3 # 程序启动时初始化数据库建表,执行一次即可 conn = sqlite3.connect("track.db") c = conn.cursor() c.execute(""" CREATE TABLE IF NOT EXISTS calculate ( earn TEXT NOT NULL, expense TEXT NOT NULL, earning_value REAL NOT NULL, expense_value REAL NOT NULL, bank_balance REAL NOT NULL ) """) conn.commit() conn.close() def earning(): new_window = Toplevel() new_window.geometry("400x400") # 收入来源输入框 text1 = Label(new_window, text="From where did you earn?") text1.pack() earn = Entry(new_window) earn.pack() # 收入金额输入框 text2 = Label(new_window, text="How much did you earn?") text2.pack() earning_value = Entry(new_window) earning_value.pack() # 提交逻辑放在earning函数内部,可直接访问同作用域的输入控件 def submit(): # 基础输入校验 earn_content = earn.get().strip() earn_val_content = earning_value.get().strip() if not earn_content or not earn_val_content: Label(new_window, text="输入不能为空", fg="red").pack() return try: earn_val = float(earn_val_content) except ValueError: Label(new_window, text="收入金额请输入数字", fg="red").pack() return conn = sqlite3.connect('track.db') c = conn.cursor() # 参数化查询避免注入,补全5个非空字段的传值,其余字段可后续加对应输入框采集 c.execute( "INSERT INTO calculate VALUES (?, ?, ?, ?, ?)", (earn_content, "", earn_val, 0.0, 0.0) ) conn.commit() c.close() conn.close() Label(new_window, text="提交成功", fg="green").pack() submit_button = Button(new_window,text='Submit',command=submit) submit_button.pack() # 主窗口逻辑 window = Tk() window.geometry("300x200") main_btn = Button(window, text="录入收入", command=earning) main_btn.pack(pady=50) window.mainloop()
关键修改说明
- 把
submit()函数移动到earning()函数内部定义,和两个输入控件处于同一作用域,直接访问控件对象获取输入值,从根源解决名称未定义的报错 - 修正所有代码缩进,符合Python语法规范
- 移除无效的
textvariable字符串传参,直接通过Entry控件的.get()方法获取用户输入 - 改用
?占位符的参数化查询写法,彻底避免SQL注入和特殊字符导致的语法错误,同时补全5个表字段对应的传值 - 修正事务提交、连接关闭的逻辑,增加基础输入校验,避免空值、非数字输入导致程序崩溃
- 补全主窗口入口逻辑,添加触发收入录入窗口的按钮,修复原代码中
earning()函数从未被调用、窗口无法打开的问题 - 移除开头多余的
from curses import window导入,避免和Tkinter窗口对象命名冲突
内容的提问来源于stack exchange,提问作者Nayan Roy
相关产品推荐
相关产品推荐

