ValueError: Invalid file path or buffer object type: <class 'tkinter.StringVar'>

被刻印的时光 ゝ 提交于 2020-12-12 04:53:03

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!