for loop/if elif statement not working correctly

Asked by Glenna

I have the following code in Sikuli that does copy and paste tasks. I want it to execute the actions inside "if not exists" when caption.png does not exist, but sometimes even if it doesn't, it is still trying to find it and returns an error that says "can't find caption.png".And sometimes it randomly jumps one idx. Can't figure out why:

for idx in range(5,106):
    if not exists("caption.png"):
        click("1406907972716.png")
        type(Key.PAGE_DOWN)
        print "skip" + str(idx)
    elif exists("caption.png"):
        click("caption.png")
        type(Key.F2)
        type("a", KeyModifier.CTRL)
        type("c", KeyModifier.CTRL)
        click("CLICKBOX-4.PNG")
        click("BOX2-4.PNG")
        type("a", KeyModifier.CTRL)
        type(Key.DELETE)
        type("v", KeyModifier.CTRL)
        type(str(idx))
        type(Key.HOME)
        type(Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE + Key.DELETE)
        click("1406907972716.png")
        type(Key.PAGE_DOWN)
        print idx
    else:
        print "nonsense" + str(idx)

Question information

Language:
English Edit question
Status:
Solved
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Solved by:
Glenna
Solved:
Last query:
Last reply:
Revision history for this message
Eugene S (shragovich) said :
#1

Hi,

May I propose some changes into your code first?

1. Use "try, except" structure
2. There is no need for "else" clause here because you really have just 2 options, the image was found or it wasn't.
3. Use exists with '0' parameter to make it more time efficient. This way, it will return the results immediately rather than waiting 3 default seconds.
4. Use loop for multiple button presses. Just to make it a bit more pretty and easy to change.

So something like that:

import org.sikuli.script.FindFailed as FindFailed #Sikuli Bug #1216338

for idx in range(5,106):
    try:
        wait("caption.png", 0)
        click("caption.png")
        type(Key.F2)
        type("a", KeyModifier.CTRL)
        type("c", KeyModifier.CTRL)
        click("CLICKBOX-4.PNG")
        click("BOX2-4.PNG")
        type("a", KeyModifier.CTRL)
        type(Key.DELETE)
        type("v", KeyModifier.CTRL)
        type(str(idx))
        type(Key.HOME)

        for i in range(24):
            type(Key.DELETE)

        click("1406907972716.png")
        type(Key.PAGE_DOWN)
        print "idx #%d" %(idx)

    except FindFailed:
        click("1406907972716.png")
        type(Key.PAGE_DOWN)
        print "skip" + str(idx)

Please try that and see if that works better for you.

Cheers,
Eugene

Revision history for this message
Jonas Maurer (jonas-maurer) said :
#2

This is for Eugene: "try, except" is meant for exception handling. Not for use in expected situations. Reason being it generates a ton of ugly and slow code on C level. Never ever use exceptions to mimic if-else behaviour.

For Glenna:
I removed a few lines of code that were redundant. Redundancy lowers robustness of your code and makes it more error prone, perhaps that is already enough of a solution.
instead of searching for caption three times per iteration, search once, and save the result in a match object.
then test wheter the match is valid,
if it is then use click on the match object instead of searching the very same picture again.
if it isn't there is no need to check if it is invalid, (that is already implied by the laws of binary fields)
check if there isn't a better way than clicking delete for Idon'tknowhowmanytimes.
pushing a button for "a lot of times" is usually a common source for errors, glitches (and inefficiency too).

for idx in range(5,106):
 match = exists("caption.png"):
    if match :
        click(m)
        type(Key.F2)
        type("a", KeyModifier.CTRL)
        type("c", KeyModifier.CTRL)
        click("CLICKBOX-4.PNG")
        click("BOX2-4.PNG")
        type("a", KeyModifier.CTRL)
        type(Key.DELETE)
        type("v", KeyModifier.CTRL)
        type(str(idx))
        type(Key.HOME)
  for c in range(25):
   type(Key.DELETE)
        click("1406907972716.png")
        type(Key.PAGE_DOWN)
        print idx
    else:
        click("1406907972716.png")
        type(Key.PAGE_DOWN)
        print "skip" + str(idx)

you can reduce the scan time of exist to 0 seconds like Eugene mentioned; use exists("caption.png",0)

Revision history for this message
Jonas Maurer (jonas-maurer) said :
#3

I had to reformat the identations due to a display glitch:

for idx in range(5,106):
 m = exists("caption.png"):
    if m :
        click(m)
        type(Key.F2)
        type("a", KeyModifier.CTRL)
        type("c", KeyModifier.CTRL)
        click("CLICKBOX-4.PNG")
        click("BOX2-4.PNG")
        type("a", KeyModifier.CTRL)
        type(Key.DELETE)
        type("v", KeyModifier.CTRL)
        type(str(idx))
        type(Key.HOME)
        for c in range(25):
            type(Key.DELETE)
        click("1406907972716.png")
        type(Key.PAGE_DOWN)
        print idx
    else:
        click("1406907972716.png")
        type(Key.PAGE_DOWN)
        print "skip" + str(idx)

Revision history for this message
Glenna (x-jingge) said :
#4

Hi Jonas,

Thank you very much! I'll do some experiment with it.