1

I'm making a tkinter program in which it will be needed to make the connection with Arduino via serial (but that's not very important).

Before explaining my problem, here is the code:

def arduino_makeConnection():

    global arduino

    try:
        arduino = serial.Serial('/dev/ttyACM0', 9600, timeout = 0)

    except:
        print "Failed to connect"
        if(time.time()-time_start<20):             
            root.after(0,arduino_makeConnection())



global time_start
time_start=time.time()
arduino_makeConnection()

So, I want to try to make connection via serial with the arduino only during 20s. After that time, I want it to give it up.

The problem is that my tkinter window doesn't open even though it prints in my console "Failed to connect" many many times until it gets the message (way before the 20 seconds have run off): RuntimeError: maximum recursion depth exceeded in cmp

I have tried to change time from 0 to 10 or 100ms on the root.after, but that doesn't solve the problem.

I think this has something to do with event handler, or something like that. However I thought that as I am not using a While or any other kind of loop, Tkinter would work...

Actually, before using the root.after I was making a While that was only breaking after the 20s or insead if the arduino was plugged in during that time. However when I searched in the internet, I realized that a loop in Tkinter is not a good idea. So, I changed to the root.after method, but now it's not working either!

Any help? Thanks in advance!

2
  • @DYZ The OP did write a loop, and root.after usually is the proper way with tkinter. The problem is recursively calling the callback in the callback. The solution is to pass the callback without calling it. Commented Apr 8, 2017 at 23:34
  • 1
    Possible duplicate of Tkinter: use root.after() properly See the second def muovi: and the first, accepted, answer. Commented Apr 8, 2017 at 23:40

2 Answers 2

3

Consider this code:

root.after(0,arduino_makeConnection())

This is exactly the same as this code:

result = arduino_makeConnection()
root.after(0, result)

And, assuming your function doesn't return anything, it's exactly the same as this:

root.after(0, None)

See the problem? The after command must be given a reference to a callable. In short, remove the parenthesis:

root.after(0,arduino_makeConnection)

Also, I highly recommend against using 0 (zero) as the first parameter. At the very least you should use 1 (one). A value of zero can have surprising side effects because you essentially create an infinite event queue that never empties.

Sign up to request clarification or add additional context in comments.

3 Comments

As I understand, callin a function with the ()'s, actually "calls" for the value that the function returns. On the other hand, calling without the ()'s, actually calls the function object. I just can't understand the difference!! I mean, by removing the ()'s, "calling callback() calls callback() calls ... " is no longer happening?
@ajcoelho: Using parenthesis calls a function. Without the parenthesis the function is not called. Instead, you are simply telling after which funtion to run in the future.
Okay! That makes sense!! Sorry, perhaps I did not understand this at first because my function doesn't actually return a thing. It's like a void function I'd say... Anyway I should have realized this faster because this is exactly what I do when creating buttons!
1

If you tried to make an MCVE, you might come up with

import tkinter as tk
root = tk.Tk()

def callback():
    print('callback')
    root.after(0, callback())
callback()

This might make it more obvious that calling callback() calls callback() calls ..., until you get the recursion error. Remove the () in the root.after call. Also use a non-zero delay. Try the above with, for instance, `root.after(100, callback).

2 Comments

It worked! I've made a little search: as I understand, callin a function with the ()'s, actually "calls" for the value that the function returns. On the other hand, calling without the ()'s, actually calls the function object. I just can't understand the difference!! I mean, by removing the ()'s, "calling callback() calls callback() calls ... " is no longer happening?
Without the ()s, the function is not called. Instead, the function object is passed to after() to be called later. The value of the expression int is the int function. The value of the expression int() is int 0 (the default return of the int function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.