Search code examples
pythontkintertkinter-button

Executing a Button command from another file?


I have started working on a GUI system where I need to import a function from one file to be executed in the main file when a button is pressed, but every time I run it I get:

AttributeError: partially initialized module 'Two' has no attribute 'sum'
  (most likely due to a circular import)

The program is supposed to input two values, Value_a and Value_b, and the function being called sum() is supposed to add the two and output a result in a new window. Here is an example of the file I want to import and its function sum():

Two.py:

from tkinter import *  #Import the tkinter module    
import One #This is the main file, One.py

def sum():
    newWindow = Toplevel(One.Window)
    newWindow.title("Sum")
    a = int(One.Value_a.get())
    b = int(One.Value_b.get())
    c = a+b
    Label(newWindow, text= str(c)).grid(row=1, column=0)

This is how the main file looks like:

One.py:

from tkinter import *
import Two

Window = Tk()
Window.title("Main Window")

Value_a = Entry(Window, width=15).grid(row=1, column=0)
Value_b = Entry(Window, width=15).grid(row=2, column=0)
my_button = Button(Window, text="Test", command=lambda: Two.sum).grid(row=3, column=0)

Window.mainloop()

When this is run, I end up getting the above error.


Solution

  • The problem is because you really do have a circular import. Module One imports module Two which imports module One... etc. However the simple fix @acw1668 suggested isn't enough to fix things because the Two module references more than just the Window attribute of the One module. My solution passes the things in module One the function in module Two needs as arguments (so the Two module doesn't need to import it to get access to them).

    Another problem with your tkinter code is discussed in the question Tkinter: AttributeError: NoneType object has no attribute , which I suggest you read.

    Below are changes to both your modules that fix all these issues.

    One.py:

    from tkinter import *
    import Two
    
    
    Window = Tk()
    Window.title("Main Window")
    
    Value_a = Entry(Window, width=15)
    Value_a.grid(row=1, column=0)
    Value_b = Entry(Window, width=15)
    Value_b.grid(row=2, column=0)
    
    my_button = Button(Window, text="Test",
                       command=lambda: Two.sum(Window, Value_a, Value_b))
    my_button.grid(row=3, column=0)
    
    Window.mainloop()
    

    Two.py:

    from tkinter import *
    
    
    def sum(Window, Value_a, Value_b):
        newWindow = Toplevel(Window)
        newWindow.title("Sum")
        a = int(Value_a.get())
        b = int(Value_b.get())
        c = a+b
        Label(newWindow, text= str(c)).grid(row=1, column=0)