使用 SQL 查询 pandas 时为何没有返回新的 DataFrame?
代码中有两处可以直接确认:command=filter_data(sql) 在创建按钮时就执行了查询,输入框的值也在创建后立即被读取。应将函数作为回调交给按钮,并在点击时读取 SQL。
AttributeError: 'NoneType' object has no attribute 'columns' 说明传给 display_data() 的对象是 None。题目没有提供 sqldf() 的导入方式和实际执行的 SQL,因此仅凭这段代码无法确定它为什么返回 None。
为什么查询没有按预期执行?
这行代码在创建按钮时就调用了函数:
btn_filter = tk.Button(frame_filter, text="Filter", command=filter_data(sql))
Python 会先执行 filter_data(sql),再把返回值传给 command,没有为按钮注册预期的查询回调。
此外,输入框刚创建时就读取了它的值:
sql = entry_value.get()
所示代码没有设置初始内容,所以此时读到的是空字符串。之后用户在输入框中输入 SQL,变量 sql 也不会随之更新。
可以先将按钮改成:
btn_filter = tk.Button(
frame_filter,
text="Filter",
command=lambda: filter_data(entry_value.get())
)
这样,点击按钮时才会读取输入并调用查询函数。
如何显示查询返回的 DataFrame?
下面是完整的相关代码。示例假设 sqldf 来自 pandasql,CSV 或 parquet 文件已加载到 df,并且 tree、frame_filter 已经创建。如果使用其他同名函数,需要按其接口调整查询调用。
import tkinter as tk
from tkinter import messagebox
from pandasql import sqldf
def display_data(dataf):
tree.delete(*tree.get_children())
tree["columns"] = list(dataf.columns)
tree["show"] = "headings"
for col in dataf.columns:
tree.heading(col, text=col)
tree.column(col, width=150)
for _, row in dataf.iterrows():
tree.insert("", "end", values=list(row))
def filter_data():
sql_input = entry_value.get().strip()
if not sql_input:
messagebox.showwarning("提示", "请先输入 SQL 查询。")
return
try:
result = sqldf(sql_input, {"df": df})
if result is None:
raise ValueError("sqldf 返回了 None,请检查 SQL 和函数来源。")
display_data(result)
except Exception as exc:
messagebox.showerror("查询失败", str(exc))
return
return result
entry_value = tk.Entry(frame_filter, width=40)
entry_value.grid(row=0, column=1, padx=5)
entry_value.insert(0, "SELECT * FROM df LIMIT 10;")
btn_filter = tk.Button(
frame_filter,
text="Filter",
command=filter_data
)
btn_filter.grid(row=0, column=2, padx=5)
两处设置需要注意:
command=filter_data传入函数本身,不加调用括号。点击按钮时,函数才会读取输入框。sqldf(sql_input, {"df": df})显式提供查询环境,让 SQL 中的表名df对应已经加载的 DataFrame。
例如,输入下面的查询可以尝试读取前 10 行:
SELECT * FROM df LIMIT 10;
如果仍然得到 None,应该检查什么?
先确认 sqldf 的实际来源和传入的 SQL。可以在查询前后临时加入:
print("SQL:", repr(sql_input))
result = sqldf(sql_input, {"df": df})
print("Result type:", type(result))
repr(sql_input) 可以帮助发现空字符串或只有空白字符的输入。还要确认查询使用了环境中提供的表名,且用于获取数据的语句是预期的 SELECT 查询。
原来的 if dataf is None: return 只会跳过显示,无法解释查询为什么没有结果。排查时应保留明确的错误提示。正常返回的 DataFrame 即使没有匹配行,也仍有 columns 属性;“结果没有行”和“结果是 None”需要分别处理。
Tkinter 按钮不会自动使用回调的返回值。return result 可供直接调用函数时使用,界面更新仍由 display_data(result) 完成。如果后续绘图需要查询结果,应另行保存。示例保留了原始 df,没有用查询结果覆盖它。
问题中粘贴的代码缺少函数体和循环体的缩进;实际 Python 文件需要像修正示例一样正确缩进。
备注:内容仅供参考。
