ValueError:无效的文件路径或缓冲区对象类型:<class 'tkinter.StringVar'>
Posted
技术标签:
【中文标题】ValueError:无效的文件路径或缓冲区对象类型:<class \'tkinter.StringVar\'>【英文标题】:ValueError: Invalid file path or buffer object type: <class 'tkinter.StringVar'>ValueError:无效的文件路径或缓冲区对象类型:<class 'tkinter.StringVar'> 【发布时间】:2018-09-03 05:12:19 【问题描述】:这是我拥有的一些代码的简化版本。在第一帧中,用户使用 'tk.filedialog' 选择了一个 csv 文件,它被绘制在画布上的同一帧上。
还有第二个框架能够绘制图表,以防跨不同框架更容易绘制。
运行此版本的代码会导致错误:“ValueError: Invalid file path or buffer object type:”。我不确定如何在不发生此问题的情况下使此代码正常工作,以便用户选择的文件绘制在具有列“a”和“b”的空图上。
import csv
import pandas as pd
import tkinter as tk
from tkinter import filedialog
from tkinter import ttk
from tkinter import messagebox
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
fig = Figure(figsize=(5,4), dpi=100)
ax= fig.add_subplot(111)
LARGE_FONT= ("Verdana", 12)
class GUI(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "GUI")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames =
for F in (Home, Graph):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(Home)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class Home(tk.Frame):
def __init__(self, parent, controller):
self.controller = controller
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10, padx=10)
ftypes = [
('CSV files','*.csv')
]
def browsefunc2():
filename = tk.filedialog.askopenfilename(filetypes=ftypes)
pathlabel2.config(text=filename)
filename = filename.get()
return filename
#this line is just used to check that hard-coding in a filename works, which it does providing 'filename = tk.StringVar()' is removed
#filename = '...'
filename = tk.StringVar()
df = pd.read_csv(filename, encoding='latin-1')
browsebutton = tk.Button(self, borderwidth=0, text="Browse", command=browsefunc2, height=1, width=10)
browsebutton.pack()
pathlabel2 = tk.Label(self, borderwidth=0)
pathlabel2.pack()
canvas = FigureCanvasTkAgg(fig, self)
df.plot.scatter('a', 'b', ax=ax)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
button2 = ttk.Button(self, text="Graph",
command=lambda: controller.show_frame(Graph))
button2.pack()
class Graph(tk.Frame):
def __init__(self, parent, controller):
self.controller = controller
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Graph", font=LARGE_FONT)
label.pack(pady=10,padx=10)
canvas = FigureCanvasTkAgg(fig, self)
#this line causes a problem as the dataframe is not recognised across frames
df.plot.scatter('a', 'b', ax=ax)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
button3 = ttk.Button(self, text="Back",
command=lambda: controller.show_frame(Home))
button3.pack()
app = GUI()
app.mainloop()
据我所知,无法将 .csv 文件上传到 ***,因此我重新创建了一个示例,但文件类型必须为 .csv。
a,b
1,10
2,32
3,23
4,5
5,4
6,66
7,7
8,19
9,31
10,44
【问题讨论】:
【参考方案1】:我没有运行你的“简化”版本的代码,因为它绝不是Minimal, Complete, and Verifiable example。
错误告诉你,当它是StringVar
时,你假设它是一个路径或缓冲区。我相信错误就在线:
df = pd.read_csv(filename, encoding='latin-1')
这要求filename
是一个路径或缓冲区对象,其中filename
上面的那一行确实是一个StringVar
对象:
filename = tk.StringVar()
df = pd.read_csv(filename, encoding='latin-1')
为了达到StringVar
或任何Variable 子类类型的值,需要使用get
方法。
filename.get()
但是,这会产生一个空字符串 ''
,这会引发另一个错误。
【讨论】:
【参考方案2】:我在 PyQt5 上遇到了非常相似的问题。不知道怎么回事,我用print(filename)
发现string
包含了过滤信息(即("*.csv")
。
使用:
savePath, _filter = QtWidgets.QFileDialog.getSaveFileName(None, "Some Title", "someFile.csv", "CSV files (*.csv)")
过滤器信息被剥离,保存工作没有错误。
【讨论】:
【参考方案3】:我在使用 PyQt5 并打开一个文件时遇到了这个问题。发现在我的情况下使用
filename = QFileDialog.getOpenFileName(self, 'Open file', '', 'csv(*.csv)')
文件对话框读取文件名 + , 'csv(*.csv)')
要从 QFileDialog 或类似的东西中获取文件名,您可以获取该“文件名”中的第一个值
file = filename[0]
【讨论】:
【参考方案4】:当您在构造函数中初始化文件名并将其传递给函数时,也会发生这种情况。
class MainWindow(QtWidgets.QMainWindow):
send_fig = QtCore.pyqtSignal(str)
def __init__(self, plot_file=None):
super(MainWindow, self).__init__()
.
.
.
self.plot_file = "./filename.csv"
self.plot(self.plot_file)
def plot(self, file_name):
print(file_name)
df = pd.read_csv(file_name, encoding='utf-8', engine='python')
这会引发错误:
引发 ValueError(msg.format(_type=type(filepath_or_buffer))) ValueError:无效的文件路径或缓冲区对象类型:类'int'
class MainWindow(QtWidgets.QMainWindow):
send_fig = QtCore.pyqtSignal(str)
def __init__(self, plot_file=None):
super(MainWindow, self).__init__()
.
.
.
self.plot(self.plot_file)
def plot(self, file_name):
print(file_name)
# file_name = "./filename.csv"
df = pd.read_csv(file_name, encoding='utf-8', engine='python')
这应该可以正常工作,您可以在函数图中定义文件名,或者简单地将其传递给构造函数:
file_name = "./filename.csv"
app = QtWidgets.QApplication(sys.argv)
ex = MainWindow(file_name)
sys.exit(app.exec_())
【讨论】:
以上是关于ValueError:无效的文件路径或缓冲区对象类型:<class 'tkinter.StringVar'>的主要内容,如果未能解决你的问题,请参考以下文章
ValueError:缓冲区 dtype 不匹配,预期为“Python 对象”但得到“双倍”
Cordova:无效数据,块必须是字符串或缓冲区,而不是对象
无效数据,块必须是字符串或缓冲区,而不是对象 - 离子和火力
从零开始的Java开发1-6-4 Java输入输出流:File类绝对路径和相对路径字节流缓冲流字符流对象序列化