The notion of "returning" values from callbacks doesn't make sense in the context of an event driven program. Callbacks are called as the result of an event, so there's nowhere to return a value to.

As a general rule of thumb, your callbacks should always call a function, rather than using functools.partial or lambda. Those two are fine when needed, but if you're using an object-oriented style of coding they are often unnecessary, and lead to code that is more difficult to maintain than it needs to be.

For example:

def compute():
    value = var.get()
    result = square(value)
    list_of_results.append(result)

button = Tk.Button(root, text='click', command = compute)
...

This becomes much easier, and you can avoid global variables, if you create your application as a class:

class App(...):
    ...
    def compute():
        ...
        result = self.square(self.var.get())
        self.results.append(result)
Answer from Bryan Oakley on Stack Overflow
Top answer
1 of 3
11

The notion of "returning" values from callbacks doesn't make sense in the context of an event driven program. Callbacks are called as the result of an event, so there's nowhere to return a value to.

As a general rule of thumb, your callbacks should always call a function, rather than using functools.partial or lambda. Those two are fine when needed, but if you're using an object-oriented style of coding they are often unnecessary, and lead to code that is more difficult to maintain than it needs to be.

For example:

def compute():
    value = var.get()
    result = square(value)
    list_of_results.append(result)

button = Tk.Button(root, text='click', command = compute)
...

This becomes much easier, and you can avoid global variables, if you create your application as a class:

class App(...):
    ...
    def compute():
        ...
        result = self.square(self.var.get())
        self.results.append(result)
2 of 3
9

Sorry for being 6 years late, but recently I figured out a good way to do this without making your code messy and hard to maintain. This is pretty much what DaveTheScientist has said, but I just want to expand on it a little. Usually, in Tkinter, if you want to have a button call a function, you do the following:

exampleButton = Button(root, text = 'Example', command = someFunc)

This will simply call someFunc whenever the button is pressed. If this function, however, takes arguments, you need to use lambdas and do something like this:

exampleButton = Button(root, text = 'Example', command = lambda: someFunc(arg1, arg2))

The above line of code will run someFunc and use the variables arg1 and arg2 as arguments for that function. Now, what you could do in a program where, a lot of the times, you would need the functions run by buttons to return values, is create a new function which is called by every button.

This function takes the function you want your button to run as a first argument, and that function's arguments afterwards.

def buttonpress(function, *args):
    value = function(*args)

Then when you create the button, you do:

exampleButton = Button(root, text = 'Example', command = lambda: buttonpress( someFunc, arg1, arg2 ))

This will run the given function (in this case, someFunc) and store the returned value in the value variable. It also has the advantage that you can use as many arguments as you want for the function your button runs.

🌐
YouTube
youtube.com › alan d moore codes
Tkinter Basics 2: Events and Callback Functions - YouTube
Learn how easy it is to use Tkinter and Python to build simple GUI applications with author Alan D Moore.Example code for this video can be found here: https...
Published   February 17, 2021
Views   4K
🌐
TutorialsPoint
tutorialspoint.com › construct-button-callbacks-with-tkinter
Construct button callbacks with Tkinter
February 15, 2024 - When working with button callbacks, it's crucial to anticipate and handle potential errors gracefully. The use of try-except blocks is an effective strategy · import tkinter as tk from tkinter import messagebox def on_button_click(): try: print("Button clicked!") except Exception as e: messagebox.showerror("Error", f"An error occurred: {str(e)}") root = tk.Tk() root.title("Error Handling in Callbacks") root.geometry("720x250") button = tk.Button(root, text="Click Me", command=on_button_click) button.pack(pady=10) root.mainloop()
🌐
Python Tutorial
pythontutorial.net › home › tkinter tutorial › tkinter command binding
Tkinter Command Binding - Python Tutorial
April 3, 2025 - This requires assigning a callback function to a specific event. When the event occurs, the callback will be invoked automatically to handle the event. In Tkinter, some widgets allow you to associate a callback function with an event using the command binding.
🌐
Quora
quora.com › How-can-I-define-a-sequence-of-callback-functions-in-Python-Tkinter
How to define a sequence of callback functions in Python Tkinter - Quora
Answer: You can create your buttons ... computable parameter(s). Button callback functions in TkInter have no parameters because they are going to be called from the Button event generating......
Find elsewhere
🌐
Python Forum
python-forum.io › thread-12007.html
Unable to return value from callback function of a button in Python Tkinter
Hi Team I am trying to get the input written in an Entry box using Tkinter, But whenever I am trying to do so I am not getting the desired result..Instead a None is getting returned. Please help My code is given below from Tkinter import * class me...
🌐
O'Reilly
oreilly.com › library › view › python-cookbook › 0596001673 › ch09s02.html
Avoiding lambda in Writing Callback Functions - Python Cookbook [Book]
July 19, 2002 - Writing a lot of callbacks that give customized arguments can look a little awkward with lambda, so this Command class gives an alternative syntax that looks nicer. For example: import Tkinter def hello(name): print "Hello", name root = Tk( ) # the lambda way of doing it: Button(root, text="Guido", command=lambda name="Guido": hello(name)).pack( ) # using the Command class: Button(root, text="Guido", command=Command(hello, "Guido")).pack( )
Authors   Alex MartelliDavid Ascher
Published   2002
Pages   608
🌐
Universidad de Granada
ccia.ugr.es › mgsilvente › tkinterbook › tkinter-events-and-bindings.htm
Events and Bindings
In this example, we use the bind method of the frame widget to bind a callback function to an event called <Button-1>. Run this program and click in the window that appears. Each time you click, a message like “clicked at 44 63” is printed to the console window. Keyboard events are sent to the widget that currently owns the keyboard focus. You can use the focus_set method to move focus to a widget: ... from tkinter import * root = Tk() def key(event): print ("pressed", repr(event.char)) def callback(event): frame.focus_set() print ("clicked at", event.x, event.y) frame = Frame(root, width=100, height=100) frame.bind("<Key>", key) frame.bind("<Button-1>", callback) frame.pack() root.mainloop()
Top answer
1 of 6
4

I cannot imagine any case and Im not sure at all if this answers your question but it maybe equivalent for what you are looking for:


The invoke method of the button seems pretty equivalent to me. So solution-1 would be:

import tkinter as tk

def hi():
    print('hello')

root = tk.Tk()
b = tk.Button(root, text='test', command=hi)
b.pack()

cmd = b.invoke
#cmd = lambda :b._do('invoke')
root.mainloop()

If this isnt what you looking for you could call the function in tcl level. Solution-2:

import tkinter as tk

def hi():
    print('hello')

root = tk.Tk()
b = tk.Button(root, text='test', command=hi)
b.pack()
cmd = lambda :root.tk.call(b['command'])
#cmd= lambda :root.tk.eval(b['command'])
cmd()
root.mainloop()

Solution 3, would be to return your function by invoke:

import tkinter as tk

def hi():
    print('hello')
    return hi

root = tk.Tk()
b = tk.Button(root, text='test', command=hi)
b.pack()
cmd = b.invoke()
print(cmd) #still a string but comparable
root.mainloop()
2 of 6
3

This is a more complex solution. It patches Misc._register, Misc.deletecommand and Misc.destroy to delete values from dict tkinterfuncs. In this example there are many print to check that values are added and removed from the dict.

import tkinter as tk

tk.tkinterfuncs = {} # name: func

def registertkinterfunc(name, func):
    """Register name in tkinterfuncs."""
    # print('registered', name, func)
    tk.tkinterfuncs[name] = func
    return name

def deletetkinterfunc(name):
    """Delete a registered func from tkinterfuncs."""
    # some funcs ('tkerror', 'exit') are registered outside Misc._register
    if name in tk.tkinterfuncs:
        del tk.tkinterfuncs[name]
        # print('delete', name, 'tkinterfuncs len:', len(tkinterfuncs))

def _register(self, func, subst=None, needcleanup=1):
    """Return a newly created Tcl function. If this
    function is called, the Python function FUNC will
    be executed. An optional function SUBST can
    be given which will be executed before FUNC."""
    name = original_register(self, func, subst, needcleanup)
    return registertkinterfunc(name, func)

def deletecommand(self, name):
    """Internal function.
    Delete the Tcl command provided in NAME."""
    original_deletecommand(self, name)
    deletetkinterfunc(name)

def destroy(self):
    """
    Delete all Tcl commands created for
    this widget in the Tcl interpreter.
    """
    if self._tclCommands is not None:
        for name in self._tclCommands:
            # print('- Tkinter: deleted command', name)
            self.tk.deletecommand(name)
            deletetkinterfunc(name)
        self._tclCommands = None

def getcommand(self, name):
    """
    Gets the command from the name.
    """
    return tk.tkinterfuncs[name]


original_register = tk.Misc.register
tk.Misc._register = tk.Misc.register = _register 
original_deletecommand = tk.Misc.deletecommand
tk.Misc.deletecommand = deletecommand
tk.Misc.destroy = destroy
tk.Misc.getcommand = getcommand

if __name__ == '__main__':
    def f():
        root.after(500, f)

    root = tk.Tk()
    root.after(500, f)
    but1 = tk.Button(root, text='button1', command=f)
    but1.pack()
    but2 = tk.Button(root, text='button2', command=f)
    but2.pack()
    but3 = tk.Button(root, text='button3', command=lambda: print(3))
    but3.pack()
    print(root.getcommand(but1['command']))
    print(root.getcommand(but2['command']))
    print(root.getcommand(but3['command']))
    but3['command'] = f
    print(root.getcommand(but3['command']))
    root.mainloop()
🌐
Noobtomaster
noobtomaster.com › python-gui-tkinter › implementing-event-handlers-and-callbacks
Implementing event handlers and callbacks - Python GUI - tkinter
Start the event loop: Finally, start the event loop that constantly waits for events to occur and calls the respective event handlers or callbacks. ... The mainloop() function is a tkinter method that continuously listens for various events happening within the GUI.
🌐
15. The Menu widget
anzeljg.github.io › rin2 › book2 › 2405 › docs › tkinter › universal.html
26. Universal widget methods - Tkinter
Cancels a request for callback set up earlier .after(). The id argument is the result returned by the original .after() call. ... Requests that Tkinter call function func with arguments args next time the system is idle, that is, next time there are no events to be processed.
🌐
Python Basics
pythonbasics.org › home › tkinter › tkinter buttons (gui programming)
Tkinter buttons (GUI Programming) - pythonbasics.org
If you click the button, the callback function is called. A note on buttons: a tkinter button can only show text in a single font. The button text can be multi line.
🌐
GitHub
github.com › python › cpython › issues › 66410
Tkinter: Don't stringify callback arguments · Issue #66410 · python/cpython
August 17, 2014 - gh-66410: Do not stringify arguments of Tkinter callback #98592
Author   serhiy-storchaka
🌐
GitHub
github.com › Qirky › Troop › issues › 21
"Exception in Tkinter callback" · Issue #21 · Qirky/Troop
January 22, 2019 - Exception in Tkinter callback Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 1550, in __call__ return self.func(*args) File "/Users/madskjeldgaard/Dropbox/scripts/sc/Troop/src/interface/conn_info.py", line 118, in store_data self.finish() File "/Users/madskjeldgaard/Dropbox/scripts/sc/Troop/src/interface/conn_info.py", line 90, in finish self.client.setup(**self.options) File "/Users/madskjeldgaard/Dropbox/scripts/sc/Troop/src/client.py", line 95, in setup self.lang = langtypes[lang](self.args) TypeError: __init__() takes 1 positional argument but 2 were given ·
Author   madskjeldgaard