ValueError:无效的文件路径或缓冲区对象类型:<class'tkinter.stringvar'=“”>

时间:2018-03-24 18:03:13

标签: python csv tkinter openfiledialog valueerror

这是我的一些代码的简化版本。在第一帧中,用户使用&t; tk.filedialog&#39;选择csv文件。它应该画在画布上的同一帧上。

还有第二个框架能够绘制图形,以防更容易在不同的框架上进行。

运行此版本的代码会导致错误:&#34; ValueError:无效的文件路径或缓冲区对象类型:&#34;。我不确定如何在没有出现此问题的情况下使此代码正常工作,以便用户在空图上选择文件图,其中包含列&#39; a&#39;和&#39; b&#39;。

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文件上传到StackOverflow,因此我重新创建了一个示例,但文件类型需要为.csv。

a,b
1,10
2,32
3,23
4,5
5,4
6,66
7,7
8,19
9,31
10,44

4 个答案:

答案 0 :(得分:1)

我还没有运行你简化的&#39;代码的版本,因为它的绝不是 a Minimal, Complete, and Verifiable example

错误告诉您,当StringVardf = pd.read_csv(filename, encoding='latin-1') 时,您正在假设某个路径或缓冲区。我相信错误就行了:

filename

这需要filename作为路径或缓冲区对象,而StringVar上面的那一行确实是filename = tk.StringVar() df = pd.read_csv(filename, encoding='latin-1') 对象:

StringVar

为了达到get或任何Variable子类类型的值,需要使用filename.get() 方法。

''

但是,这会导致空字符串from kivy.app import App from kivy.uix.widget import Widget from kivy.uix.button import Button from kivy.uix.image import Image from kivy.graphics.texture import Texture from kivy.clock import Clock import cv2 import numpy as np class NormalImage(Image): def __init__(self, **kwargs): super(NormalImage, self).__init__(**kwargs) self.size = (600, 600) self.pos = (0, 0) self.img = cv2.imread('img.jpg') cv2.imshow("normal image", self.img) buf1 = cv2.flip(self.img, 0) buf = buf1.tostring() image_texture = Texture.create(size=(self.img.shape[1], self.img.shape[0]), colorfmt='bgr') image_texture.blit_buffer(buf, colorfmt='bgr', bufferfmt='ubyte') self.texture = image_texture class BinaryImage(Image): def __init__(self, **kwargs): super(BinaryImage, self).__init__(**kwargs) self.size = (600, 600) self.pos = (300, 0) img = NormalImage().img hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) hsvMin = np.array([19,150,100]) hsvMax = np.array([30,255,255]) mask = cv2.inRange(hsv,hsvMin, hsvMax) cv2.imshow("mask", mask) buf1 = cv2.flip(mask, 0) buf = buf1.tostring() image_texture = Texture.create(size=(mask.shape[1], mask.shape[0]), colorfmt='bgr') image_texture.blit_buffer(buf, colorfmt='bgr', bufferfmt='ubyte') self.texture = image_texture class RootWidget(Widget): def __init__(self, **kwargs): super(RootWidget, self).__init__(**kwargs) self.add_widget(NormalImage()) self.add_widget(BinaryImage()) class ImageApp(App): def build(self): return RootWidget() def on_stop(self): cv2.destroyAllWindows() if __name__ == '__main__': ImageApp().run() ,这会引发另一个错误。

答案 1 :(得分:0)

我对PyQt5有一个非常相似的问题。不确定发生了什么,我使用了print(filename),发现string包含了过滤器信息(即("*.csv")

使用:

savePath, _filter = QtWidgets.QFileDialog.getSaveFileName(None, "Some Title", "someFile.csv", "CSV files (*.csv)")

过滤器信息被删除,保存工作没有错误。

答案 2 :(得分:0)

我遇到了PyQt5并打开文件的问题。发现在我的情况下使用

filename = QFileDialog.getOpenFileName(self, 'Open file', '', 'csv(*.csv)')

文件对话框读取文件名+,'csv(*。csv)')

要仅从QFileDialog之类的文件中获取文件名,可以在该“文件名”中获取第一个值。

file = filename[0]

答案 3 :(得分:0)

当您在构造函数中初始化文件名​​并将其传递给函数时,也会发生这种情况。

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_())