how to pass a variable between multiple scripts

Asked by Benjamin Bruffey

I want to be able to pass a variable that is used in multiple scripts:

Let's say I have 5 scripts, the initial script, script1.sikuli will start to increment a variable

#script1.sikuli

i = 0
i += 1
i += 1
i += 1

the variable i now equals 3, I now want to pass this value, 3, to the next script, script2.sikuli and add 3 additional values to it, now i should equal 6, then pass this new i = 6 to script3.sikuli, and so on and so forth, so that in script5.sikuli I will be able to use the final value of i for a popup to show how many errors were found (i increments +1 for every error found)

thanks

Question information

Language:
English Edit question
Status:
Answered
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:
Revision history for this message
Aravind (a4aravind) said :
#1

You should be able to achieve this by making an xml-rpc call from script1 to script2, script2 to script3, and so on though I'm not sure that this will be the easiest way to accomplish your goal.

Define simple methods in script2, script3, script4, etc and and make corresponding calls to them where you can pass the value of i (from script1 to script2, script2 to script3, etc)

Thanks.

Revision history for this message
RaiMan (raimund-hocke) said :
#2

@ Aravind
principally ok, but for this case (see https://answers.launchpad.net/sikuli/+question/237151) a bit oversized ;-)

@Benjamin
2 possibilities:

-- 1.
use exit(n) in a script and give the return code as parameter to the next script run

-- 2.
you might use a file as intermediate storage

have a file in the same folder as the scripts (e.g. current_value.txt)

- to get the current value:
# supposing it only contains a number
import os
f = open(os.path.join(os.path.dirname(os.path.dirname(getBundlePath()), "current_value.txt"))
currentValue = int(f.readline().strip())
f.close()

now you have your current number in currentValue

comment:
os.path.dirname has to be applied twice to get the parent folder of the running script, because getBundlePath() returns a path with a trailing \

- to write a new value:
f = open(os.path.join(os.path.dirname(os.path.dirname(getBundlePath()), "current_value.txt"), "w")
print >> f, str(currentValue)
f.close()

Revision history for this message
RaiMan (raimund-hocke) said :
#3

the print can also be:
print >> f, currentValue

because in print all parameters are auto-converted to strings

Revision history for this message
Victor (victor1986) said :
#4

I know this solution may have issues but here it goes anyway :)

You can always pass information using the Clipboard, the caveat is that you should use the try() method described here https://answers.launchpad.net/sikuli/+question/229988 or run the script from the command line

The problem with using visual triggers is that Sikuli image search steals focus (havent tried onAppear, but i know that at least click() and exists() steal window focus). And this can seriously disrupt actions like mouse clicks and hovers etc. So, how to get around it?

You can write stuff to Clipboard!

Here is the listener

x = 0
while x < 1
    trigger = Env.getClipboard().strip()
    if trigger == 'whateverTriggesTheListener'
        x=2
    else:
        x=x
    wait(1)

And here is what is passing data to the listener

    from java.awt.datatransfer import StringSelection #Stick this in the top section of the script
    from java.awt.datatransfer import Clipboard #Stick this in the top section of the script
    from java.awt import Toolkit #Stick this in the top section of the script

    toolkit = Toolkit.getDefaultToolkit() #More info here http://stackoverflow.com/questions/10392033/clearing-windows-clipboard-while-using-sikuli-or-jython
    clipboard = toolkit.getSystemClipboard()

    vtVarOne = Env.getClipboard().strip() #just takes whatever is in the clipboard. Preferably text though...
    vtVarTwo = Env.getClipboard().strip() #Just to show that jou can call the clipboard several times
    vtVarThree = 'whateverTriggesTheListener' #This is the trigger or whatever

    strOut = vtVarOne + " first read worked " + vtVarTwo + " and so did the other"
    popup(strOut)

    clipboard.setContents(StringSelection(vtVarThree), None) #Throws in vtVarThree in the Clipboard

    switchApp("Notepad") #Assuming you have Notepad or Notepad++ open...
    type("v", KEY_CTRL) #Demonstrating that indeed, the clipboard worked :)

So you can use timed events to get this done and then use the Clipboard to send stuff from one script to the other. Its similar to writing to a file... but without needing a file.

If you arent running the scripts in parallell but rather in tandem you should use the argv method.

Simply put, in your active script type:

    vtVarOne = "TheTextYouWantToPassWithoutSpaces"
    vtVarTwo = "OtherVar"
    cmd = r'C:\--PATH TO--\SikuliX\runIDE.cmd -r G:\-- PATH TO SCRIPT --\SCRIPT.sikuli --args ' + str(vtVarOne) + ' ' + str(vtVarTwo)
    openApp(cmd)

And in the receiver you type:

    import sys
    rVarOne = int(sys.argv[1])
    rVarTwo = int(sys.argv[2])
    rReallyReallyLongString = Env.getClipboard().strip() #The clipboard is just so convenient
    #... and so on

Now you have two more ways to solve an old problem.

Can you help with this problem?

Provide an answer of your own, or ask Benjamin Bruffey for more information if necessary.

To post a message you must log in.