Как передать переменную в модулированных файлах? - PullRequest
0 голосов
/ 26 августа 2018

У меня есть функция askopenfilename() внутри моего основного файла python, которая получает каталог файлов от пользователя при нажатии кнопки.Мой основной файл называется payroll.py.

У меня есть еще один файл с именем dataframes.py, в котором есть функция, которая импортирует файлы Excel с помощью функции read_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 голосов
/ 26 августа 2018

Если вы хотите, чтобы 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...