问题
Here is a simplified version of some code that I have. In the first frame, the user selects a csv file using 'tk.filedialog' and it is meant to be plotted on the same frame on the canvas.
There is also a second frame that is capable of plotting the graph in case it is easier to do it across a different frame.
Running this version of the code results in the error: "ValueError: Invalid file path or buffer object type: ". I am not sure how to get this code to work without this problem occurring, so that the user selected file plots on the empty graph with columns 'a' and '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()
As far as I'm aware it's not possible to upload a .csv file onto StackOverflow so I have recreated an example one, but the file type needs to be .csv.
a,b
1,10
2,32
3,23
4,5
5,4
6,66
7,7
8,19
9,31
10,44
回答1:
I haven't run your 'simplified' version of the code because it's by no means a Minimal, Complete, and Verifiable example.
The error tells you that you're assuming something is a path or buffer when it is StringVar
. I believe the error is on the line:
df = pd.read_csv(filename, encoding='latin-1')
this requires filename
to be a path or buffer object where as on the very line above filename
is indeed a StringVar
object:
filename = tk.StringVar()
df = pd.read_csv(filename, encoding='latin-1')
In order to reach the value of StringVar
or any of the Variable subclass types, one needs to use get
method.
filename.get()
However, that would result an empty string, ''
which would raise another error.
回答2:
I had a very similar problem with PyQt5. Not sure what was going on, I used print(filename)
and found that the string
included the filter information (i.e. ("*.csv")
.
Using:
savePath, _filter = QtWidgets.QFileDialog.getSaveFileName(None, "Some Title", "someFile.csv", "CSV files (*.csv)")
the filter info was stripped off and saving worked without error.
回答3:
I ran into this problem with PyQt5 and opening a file. Found that when in my case using
filename = QFileDialog.getOpenFileName(self, 'Open file', '', 'csv(*.csv)')
that the file dialog reads in the filename + , 'csv(*.csv)')
To get just the filename from something like QFileDialog or something similar you can grab the first value in that 'filename'
file = filename[0]
回答4:
This also happens when you initialize file name inside the constructor and pass it over to a function.
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')
This raises an error:
raise ValueError(msg.format(_type=type(filepath_or_buffer))) ValueError: Invalid file path or buffer object type: class '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')
This shoud work fine, either you define file name in the function plot or simply pass it the constructor as:
file_name = "./filename.csv"
app = QtWidgets.QApplication(sys.argv)
ex = MainWindow(file_name)
sys.exit(app.exec_())
来源:https://stackoverflow.com/questions/49468065/valueerror-invalid-file-path-or-buffer-object-type-class-tkinter-stringvar