如何在调制文件中传递变量?

时间:2018-08-25 22:36:01

标签: python pandas tkinter

我的主python文件中有一个askopenfilename()函数,当按下按钮时,该函数将从用户获取文件目录。我的主文件名为payroll.py

我还有另一个名为dataframes.py的文件,该文件具有使用read_excel()函数导入excel文件然后处理数据的功能。

此代码在payroll.py中:

import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
import dataframes


class GUI(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("SportClips Automation 0.0.1")
        self.geometry('500x500')
        self.resizable(width=False, height=False)

        names = ['Instructions', 'Payroll']
        self.nb = self.create_notebook(names)
        self.menu = self.create_menus()

        tab = self.nb.tabs['Instructions']
        tk.Label(tab, text='-Select the "Payroll" tab to run Stylist 
Compensation Worksheets').pack()

        image = tk.PhotoImage(file="1.png")
        tk.Label(tab, image=image).pack()

        self.mainloop()

    def create_notebook(self, names):
        nb = MyNotebook(self, names)
        nb.pack()

        def add_label(parent, text, row, column):
            label = ttk.Label(parent, text=text)
            label.grid(row=row, column=column, sticky=tk.N, pady=10)
            return label

        def payroll():
            nb.pr = dataframes.runpayroll(nb.name)

        def getname():
            nb.name = filedialog.askopenfilename(title="Select file",
                                              filetypes=(("excel files", 
"*.xls"), ("all files", "*.*")))

        tab = nb.tabs['Payroll']
        add_label(tab, 'Click this button to process payroll', 1, 8)
        b1 = ttk.Button(tab, text="Run Payroll", command= payroll())
        b1.grid(row=2, column=8)
        b2 = ttk.Button(tab, text="Select SAR file", command=lambda: 
getname())
        b2.grid(row=3, column=8)

        return nb

    def create_menus(self):
        menu = tk.Menu(self, tearoff=False)
        self.config(menu=menu)
        sub_menu = tk.Menu(menu, tearoff=False)
        menu.add_cascade(label="File", menu=sub_menu)
        sub_menu.add_separator()
        sub_menu.add_command(label='Exit', command=self.destroy)
        return menu


class MyNotebook(ttk.Notebook):

    def __init__(self, master, names):
        super().__init__(master, width=795, height=475)

        # Create tabs & save them by name in a dictionary
        self.tabs = {}
        for name in names:
            self.tabs[name] = tab = ttk.Frame(self)
            self.add(tab, text=name)


GUI()

但是我猜这个错误:AttributeError: 'MyNotebook' object has no attribute 'name'

1 个答案:

答案 0 :(得分:1)

如果您希望runpayroll能够访问name,则必须将其作为参数传递。

但是更大的问题是,您似乎并没有name来通过它。

您在任何地方唯一调用name的是该getname()函数中的局部变量,该变量在该函数外部不可用。您所要做的只是return name,但调用方对返回值不做任何事情,因为它只是Tkinter命令回调。

您需要考虑将这些内容存储在何处。通常的答案是创建一个类(或者是Notebook的子类,或者是拥有Notebook的“控制器”类),然后将它们存储为实例变量。作为次等选择,您有时可以将事物存储为全局(或非局部)变量。但是,无论您决定执行哪种操作,都必须有人将值分配给该实例或全局变量。然后,您可以将其传递给run_payroll

在这种情况下,您似乎已经有一个MyNotebook类,并且正在创建该类的实例,所以也许这是存储内容的正确位置。

我们正在这样做,没有理由return从某个函数中调用方将忽略结果的任何内容。而且,您不需要lambda: payroll();您可以只使用payroll来达到相同的效果,但更易于理解(甚至更有效)。

所以:

def create_notebook(self, names):
    nb = MyNotebook(self, names)
    nb.pack()
    # …

    def payroll():
        nb.pr = dataframes.runpayroll(nb.name)

    def getname():
        nb.name = filedialog.askopenfilename(title="Select file",
                                             filetypes=(("excel 
files", "*.xls"), ("all files", "*.*")))    
    # …

现在,只需更改runpayroll即可使用该值:

def runpayroll(name):
    df_sar = pd.read_excel(name,
                           sheet_name=0, header=None, skiprows=4)