Importing user defined Python modules in Sikuli

Asked by Rajaraman Swaminathan

I want to know how to import user defined modules which the user may write in python into Sikuli. My code is not able to recognize the modules i write and stored up in a <Module>.py file. Also i want to know if such a thing is possible if i use pure Jython instead. I have tried adding the module to the Lib directory path as well which obtained after extracting the sikuli-script.jar file. Is there an alternative to the exec method already outlined in the following link:

https://answers.launchpad.net/sikuli/+question/102003

exec open("<Module Path>").read()
<Function_Name>(*params)

It would also be of help if some one can help me on how to import modules like PIL Image module in Python. This is reporting that after adding the Module to sys.path that it is not able to import the _imaging.pyd file. How to import pyd files of Python in Sikuli?

Question information

Language:
English Edit question
Status:
Answered
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:

This question was reopened

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

I use execfile() to import my basic helpers, that I need in more complex scripts and I have a central image repository.

Python modules, that are not available in the Jython environment, cannot be imported.

The only way to get around this is to use Python as main system and make the Sikuli functionality available by importing the Sikuli modules. See discussion https://answers.launchpad.net/sikuli/+question/108782.
Unfortunately with version 0.10 there are still some open questions with this approach (worked with 0.9.9).

Revision history for this message
Edu (karlmicha) said :
#2

You can import user defined python modules in a Sikuli script by either putting them in the Sikuli installation directory, or adding the module directory to sys.path. You can even import other Sikuli scripts as python modules. Suppose you have /somedir/myutil.sikuli/myutil.py, then in your main Sikuli script do

import sys
sys.path.append('/somedir/myutil.sikuli')
import myutil

If myutil.py contains images, you have to specify the full pathname to the image files in myutil.py, for example:

click('/somedir/util.sikuli/' + IMAGE)

otherwise Sikuli cannot find the image files when you call a method in myutil from the main script.

I use a small python module that adds all directories with name *.sikuli in my script directory to sys.path, so in any of my scripts I import that module first and then I can import all my other Sikuli modules.

Also, I run all my scripts from the commandline (basically java -jar sikuli-script.jar script.py) rather than in the IDE. The IDE does not clear its state everytime you hit the Run button, so any modules that were previously imported will not be imported again, which makes development a pain. I only use the IDE to capture images, and I use one script for all images, which I can then import into other scripts.

Revision history for this message
Rajaraman Swaminathan (rajaraman-swaminathan) said :
#3

Thanks Edu for the reply. I guess best option for me is to import Sikuli modules into a Python environment like Raiman had also pointed out.

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

@Edu

Interesting solution. Thanks.

To avoid the use of full path for the images you can use setBundlePath() to your image directory.

Your solution can even be optimized in my direction (have basic scripts and images in the script folder for portability):

import sys
sys.path.append(getBundlePath())
import myutil # contained in the scriptfolder

This approach makes it possible, to create portable scripts.

Revision history for this message
Tsung-Hsiang Chang (vgod) said :
#5

Tsung-Hsiang Chang suggests this article as an answer to your question:
FAQ #1114: “Importing user defined Python modules in Sikuli”.

Revision history for this message
Gregor Kopka (mailfrom-launchpad-net) said :
#6

As the IDE recycles the python interpreter instance you'll encounter the problem that changes to the myutil modules are not recognized until you restart the IDE.

A workaround enableing you to click 'run' in the IDE again after changing myutil use the following construct:
========================================================
import sys

# extend sys.path only once, else it'll get longer and longer with each click on 'run'
if getBundlePath() not in sys.path:
  sys.path.append(getBundlePath())

# clean out references to myutil to have it being imported again
# system.modules
if 'myutil' in sys.modules:
  del sys.modules['myutil']
# current scope
myutil = None
del myutil

# freshly import myutil from the scriptfolder
import myutil
========================================================

This may lead to memleaks (depending on what you do in myutil and how smart the gc of jython is), but is way better than having to restart the IDE each time you change something in myutil.

Keep in mind that the garbace collector in jython won't call __del__ on new-style classes, so don't rely on it to clean up!

Revision history for this message
Gregor Kopka (mailfrom-launchpad-net) said :
#7

in case you have more files in your myutil module, and not only __init__.py:

n = 'myutil'
for i in sys.modules.keys():
  if n == i[:len(n)]:
    del sys.modules[i]

Revision history for this message
Tsung-Hsiang Chang (vgod) said :
#8

Gregor, thanks for this tip. It would be very helpful for the people who need to write modules.

Revision history for this message
Kakha Kakhidze (kakhak) said :
#9

Gregor, thanks for that.
Would be great if developers add in Sikuli method like setModulePath() for external python modules (like setBundlePath())

Revision history for this message
Rajaraman Swaminathan (rajaraman-swaminathan) said :
#10

How do i pass parameters in the command:

java -jar sikuli-script.jar Script.sikuli

If i run the above command with parameters :

java -jar sikuli-script.jar LoadBrwser.sikuli "IE"

then i get the following error after the scirpt is executed successfully taking into account the actual parameter value:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String ind
ex out of range: -1
        at java.lang.String.substring(Unknown Source)
        at edu.mit.csail.uid.ScriptRunner.getPyFrom(ScriptRunner.java:86)
        at edu.mit.csail.uid.ScriptRunner.runPython(ScriptRunner.java:80)
        at edu.mit.csail.uid.SikuliScript.main(SikuliScript.java:76)

I am not able to trace why the above error is coming. Any help would be good. Do we have a valid option at all of passing parameters to Sikuli scripts from jython command line?

Revision history for this message
Tsung-Hsiang Chang (vgod) said :
#11

Use sikuli-ide.sh (or sikuli-ide,bat) --args to pass parameters to Sikuli scripts.
You can't do this using sikuli-script.jar yet.

Revision history for this message
Kakha Kakhidze (kakhak) said :
#12

Unfortunately I have problem with import.
When I use keyword 'with' I get such error:

SyntaxError: ("'with' will become a reserved keyword in Python 2.6", ('C:\\scripts\\robot.sikuli\\grtools.py', 60, 1, ''))

Here is a piece of code from grtools.py:
bReg = Region(473,377,752,434)
bLoc = Location(bReg.getX()+bReg.getW()-25, bReg.getY()+bReg.getH()/2-5)
def battle():
 with bReg:
  click(bLoc)
....

Revision history for this message
Tsung-Hsiang Chang (vgod) said :
#13

Did you import sikuli modules in your scripts?
Add "from sikuli.Sikuli import *" in the beginning of your each py module.

Revision history for this message
Kakha Kakhidze (kakhak) said :
#14

Does not matter, still exists.

Edited as your advice:

from sikuli.Sikuli import *

bReg = Region(473,377,752,434)
bLoc = Location(bReg.getX()+bReg.getW()-25, bReg.getY()+bReg.getH()/2-5)
def battle():
 with bReg:
  click(bLoc)
....

Revision history for this message
Rajaraman Swaminathan (rajaraman-swaminathan) said :
#15

Sean,

Does this mean that i can pass parameeters while running as .skl file :

Sikuli-IDE.bat LoadBrowser.skl "IE"

which i can run directly from command line.I am able to pass parametrs to .sikuli using the .bat file:

Sikuli-IDE.bat LoadBrowser.sikuli "IE"

This will launch the sikuli IDE and i have to run the script from that with parameters.

Revision history for this message
Gregor Kopka (mailfrom-launchpad-net) said :
#16

Kakha,

i linked the relevant bug ('with' in user modules) against this.

Revision history for this message
Kakha Kakhidze (kakhak) said :
#17

Thank you Gregor,
Hope It will be corrected with new release.

Revision history for this message
randomcrash (randomcrash) said :
#18

Hi Edu,

Thanks for your solution but I tried myself a simple case, when try to:

import myutil

sikulix complain that "name 'click' is not defined"

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

@randomcrash

--1: post your own questions, so everyone can see it. Does not make sense, to add asking comments to 8 year old questions

--2. use 1.1.4 and read the docs:
https://sikulix-2014.readthedocs.io/en/latest/scripting.html#importing-other-sikuli-scripts-reuse-code-and-images

Revision history for this message
randomcrash (randomcrash) said :
#20

@RaiMan

Thanks, the docs of 1.1.4 really helps me.

Can you help with this problem?

Provide an answer of your own, or ask Rajaraman Swaminathan for more information if necessary.

To post a message you must log in.