James Cook
James Cook

Reputation: 344

Store pandastable dataframe into variable

I currently have the below script that reads an imported csv file and displays as pandastable in the tkinter GUI.

As the file is imported its adds x2 additional columns self.table.addColumn("Current Status") and self.table.addColumn("Assign Technician").

How can I store the updated pandastable dataframe into a variable outside of class TestApp(tk.Frame): so that I can call other functions on the dataframe later in my code?

I have used the global variable before so that I can call a variable created from within a function outside of it later but not sure if thats what I need for this purpose.

import csv
import tkinter as tk
import tkinter.ttk as tkrttk
from tkinter import *
from tkinter import filedialog

import pandas as pd
from pandastable import Table, TableModel



root = tk.Tk()
root.geometry("2000x1000")
root.title('Workshop Manager')


def select_input_file():
    global input_file_path
    input_file_path = filedialog.askopenfilename(
    filetypes=(("CSV files", "*.csv"),))
    app = TestApp(root, input_file_path)
    app.place(bordermode = INSIDE,height = 500, width = 2000, x =0, y=50)
    

class TestApp(tk.Frame):
     def __init__(self, parent, input_file_path, editable = True, enable_menus = True):
        super().__init__(parent)
        self.table = Table(self, showtoolbar=False, showstatusbar=False)
        self.table.importCSV(input_file_path)
        self.table.show(input_file_path)
        self.table.addColumn('Current Status')
        self.table.addColumn('Assign Technician')
        self.table.autoResizeColumns()

root.mainloop()

Upvotes: 1

Views: 507

Answers (2)

anon01
anon01

Reputation: 11171

Avoid global to achieve this.

Currently, all your stateful variables exist in the module (file). You can do the same for your table, outside of TestApp, and then pass it though __init__:

import csv
import tkinter as tk
import tkinter.ttk as tkrttk
from tkinter import *
from tkinter import filedialog

import pandas as pd
from pandastable import Table, TableModel


table = Table(showtoolbar=False, showstatusbar=False)

root = tk.Tk()
root.geometry("2000x1000")
root.title('Workshop Manager')


def select_input_file():
    global input_file_path
    input_file_path = filedialog.askopenfilename(
    filetypes=(("CSV files", "*.csv"),))
    app = TestApp(root, input_file_path)
    app.place(bordermode = INSIDE,height = 500, width = 2000, x =0, y=50)
    

class TestApp(tk.Frame):
     def __init__(self, parent, input_file_path, editable = True, enable_menus = True, table=table):
        super().__init__(parent)
        self.table = table
        self.table.importCSV(input_file_path)
        self.table.show(input_file_path)
        self.table.addColumn('Current Status')
        self.table.addColumn('Assign Technician')
        self.table.autoResizeColumns()

root.mainloop()

Your table object is now accessible to anything that can see the module namespace. Here table is a mutable object, and all changes will be reflected to any function that accesses that object.

One suggestion: it is preferable to separate out your definitions (classes, functions) from your stateful bits that are created at run time. This will greatly help clarify dependencies. It is typical to use the line if __name__ == "__main__": at the bottom of the file to start the "script" part of your app, keeping all definitions above. I've seen some packages (looking at you, Flask!) break this convention a bit, and it can cause headaches.

On that note, your select_input_file function has a few issues. There's no good reason to create an app instance there. A better option would be to make this a method in the App class for example.

Upvotes: 0

Pankaj Parashar
Pankaj Parashar

Reputation: 10192

You don't necessarily need a global variable here. You can directly access the member attributes of a class by using the object itself. So in this case, you can access the table attr of the class TestApp using app.table, which would look something like this,

def select_input_file():
    #...
    app = TestApp(root, input_file_path)
    app.place(bordermode = INSIDE,height = 500, width = 2000, x =0, y=50)

    df = app.table     # contains the updated table which can be passed to other functions
    newFunc( df )      # sample call

Upvotes: 1

Related Questions