1

I´m new to python and practicing, and I have now written this piece of coding, but I´m getting an error I do not know how to resolve, could someone help me please?

This is my code:

from tkinter import *

root = Tk()

name = 'donut'

def printInput(event, name):
    print("Your name is %s, and you are years old." % (name))

button_1 = Button(root, text="Submit")
button_1.bind("<Button-1>", printInput)
button_1.pack()

root.mainloop()

And when I click on submit, I get this error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\error\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1699, in __call__
    return self.func(*args)
TypeError: printInput() missing 1 required positional argument: 'name'

What am I doing wrong?

Thanks!

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
CandyGum
  • 461
  • 3
  • 7
  • 19
  • In `print("Your name is %s, and you are %s years old." % name)` you have two `%s` placeholders but you only supply one piece of data. You need `print("Your name is %s, and you are %s years old." % name, something_else_here)` – roganjosh Feb 28 '17 at 12:42
  • @roganjosh Oh, thanks, I fixed it now, but I get the same error... The error only comes when I click on submit though – CandyGum Feb 28 '17 at 12:44
  • 1
    Saying "I fixed it now, but get the same error" obviously means you didn't fix it right. You should be more specific and edit your question to reflect what you supposedly "fixed" and the *exact* error message. – l'L'l Feb 28 '17 at 12:50
  • I'm going to tag this with tkinter tag. I can get it to work but it only prints the message when I close the window at the end. It's been a while since I did anything with tkinter so I don't remember the proper way to do this. – roganjosh Feb 28 '17 at 12:51
  • @l'L'l Edited question with the new code – CandyGum Feb 28 '17 at 12:54
  • You didn't add the other input as roganjosh pointed out; there should be another variable after name. (eg. `% name, age`)... – l'L'l Feb 28 '17 at 12:56
  • @PaulRooney Can you show me what the code would be if I did what you said? Because if I go with only one argument, event, it won´t print the name? – CandyGum Feb 28 '17 at 12:57
  • @l'L'l I removed the other %s instead – CandyGum Feb 28 '17 at 12:57

2 Answers2

3

tkinter will call your function with only one argument. Your function expects 2 so it breaks. Just refer to the global value name from the function

def printInput(event):
    print("Your name is %s, and you are years old." % (name))

For a small learner program this might be ok but you may wish to find a nicer way to get that value into your function than using a global as you create larger more complex and/or reusable scripts.

One way to do that is to partially apply your function before passing it to the tkinter widget using the library function functools.partial.

from functools import partial
# ...

button_1.bind("<Button-1>", partial(printInput, name=name))

You can create a new function with the name keyword argument preloaded and pass it to the button, this function only expects one argument and it all works ok.

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
  • 1
    I'm being a little pedantic and maybe off topic, but this isn't quite currying, this is partial application. If it were currying it would look more like: `from somewhere import curry;def printInput(name, event): ...;printInput=curry(printInput);button_1.bind("", printInput(name))` – Oli Sep 08 '19 at 11:31
  • 1
    Yeah I sure. Thinking about it the two aren’t exactly the same. I’ll change the answer. Thanks for pulling me up on it. – Paul Rooney Sep 08 '19 at 11:34
3

You have the function printInput which has two parameters, but when it is called, tkinter only passes it one argument, i.e. the event.

One way to pass the name argument as well is to use a lambda function:

button_1.bind("<Button-1>", lambda event:printInput(event,name))

This will pass the global name variable to the function as an argument.

Oli
  • 2,507
  • 1
  • 11
  • 23