Name Error using Java classes in imported script --- workaround

Asked by Benny Phanichkul

***** workaround

when importing other .sikuli, use Java's fully qualified package names in the imported modules.

see comment #2 below

If you decide to use the direct import of the contained .py files, you have to import each class package like:

from some.java.package import Class

so you can use later
x = Class()

see comment #4 below

----------------------------------------------------------------
Hi,

I created a utility module that will assist me in taking screenshots when my script runs into an error, but I'm getting "NameError: global name 'Rectangle' not defined" and am not sure why.

Here are my functions:
--------------------------------------------------
my file directory is this
--------------------------------------------------

./testMain
./testUtility

--------------------------------------------------
testMain contains
--------------------------------------------------

import os
myPath = os.path.dirname(getBundlePath())
if not myPath in sys.path: sys.path.append(myPath)

from testUtility import *

takeScreenshotOfError("myError.jpg")

--------------------------------------------------
testUtility contains
--------------------------------------------------
from java.awt import Robot
from java.awt import Toolkit
from java.awt import Rectangle
from java.io import File
from javax.imageio import ImageIO

def takeScreenshotOfError(filename):
 testResultsPath = "c:\\test\\"

 robot = Robot()
 theImage = robot.createScreenCapture(Rectangle(Toolkit.getDefaultToolkit().getScreenSize()))
 ImageIO.write(theImage, "jpg", File(testResultsPath+filename))

-----------------------------------------

this is the error i get when i run testMain in sikuli IDE
 theImage = robot.createScreenCapture(Rectangle(Toolkit.getDefaultToolkit().getScreenSize())) NameError: global name 'Rectangle' is not defined

can anyone help me with this? the code works when when it's all contained in one file, but i need it to be modular so other sikuli scripts can use the screenshot function.

thanks

Question information

Language:
English Edit question
Status:
Solved
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Solved by:
Benny Phanichkul
Solved:
Last query:
Last reply:
Revision history for this message
RaiMan (raimund-hocke) said :
#1

Only to be sure: After changing anything in imported modules, you have to restart the IDE.

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

Might be a bug. I will report it to the developers.

See below for a workaround.

Using Sikuli's import feature (as you did), it seems, that the imports do not populate the global namespace.
Using the fully qualified package names works.

when using Jythons import (directly importing the testUtility.py) it works as expected.

I suggest, to make a class, to be more flexible for the future.

Supposing all .sikuli in same directory.

BTW:
-- use raw strings r"some absolute path" - no need to double the backslashes
-- no need to use Java's IO - use Jythons's file() instead

**** case using direct import

--- the testUtility module
from sikuli.Sikuli import * # needed only if Sikuli features are used
from java.awt import *
from javax.imageio import *
import os

class ScreenLog:
    def __init__(self, p = r"c:\test", t="jpg"):
        self.myRobot = Robot()
        self.logPath = p
        self.imgType = t
    def takeScreenshotOfError(self, filename):
     ImageIO.write(self.myRobot.createScreenCapture(Rectangle(Toolkit.getDefaultToolkit().getScreenSize())),
            self.imgType, file("%s.%s"%(os.path.join(self.logPath,filename),self.imgType),"w"))

--- the main script:
import os
myPath = os.path.join(os.path.dirname(getBundlePath()), "testUtility.sikuli")
if not myPath in sys.path: sys.path.append(myPath)
from testUtility import *

sl = ScreenLog()
sl.takeScreenshotOfError("test")

**** case using Sikuli's import feature
use fully qualified package names for Java packages

--- the testUtility module
from sikuli.Sikuli import *
import java.awt as Jawt
import javax.imageio as Jimgio
import os

class ScreenLog:
    def __init__(self, p = r"c:\test", t="jpg"):
        self.myRobot = Jawt.Robot()
        self.logPath = p
        self.imgType = t
    def takeScreenshotOfError(self, filename):
     Jimgio.ImageIO.write(self.myRobot.createScreenCapture(Jawt.Rectangle(Jawt.Toolkit.getDefaultToolkit().getScreenSize())),
            self.imgType, file("%s.%s"%(os.path.join(self.logPath,filename),self.imgType),"w"))

--- the main script
impPath = "/Users/rhocke/Downloads/15_Sikuli/00_rc3"
if not impPath in sys.path: sys.path.append(impPath)
from testUtility import *

sl = ScreenLog()
sl.takeScreenshotOfError("test")

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

Here you have the base for a solution using Sikuli's Java Screen class:

import org.sikuli.script.Screen as JScr
s = JScr()
bufImg = s.capture().getImage()

bufImg contains a Java buffered image of the screenshot.

Have a look at http://sikuli.org/doc/java-x/org/sikuli/script/Screen.html for the possible parameters of capture()
(this is another capture() as the one on the Python/Jython API level!)

Revision history for this message
Benny Phanichkul (benny-w) said :
#4

Thanks RaiMan,

Your direct import solution worked for me. However, I had to explicitly call out the packages I wanted to import (import * did not work even after restarting the IDE), so my imports in testUtility module (direct import method) became:

from sikuli.Sikuli import * # needed only if Sikuli features are used
from java.awt import Toolkit
from java.awt import Rectangle
from java.awt import Robot
from javax.imageio import ImageIO
import os

any idea why import * does not work? could this be another bug?

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

I have to admit, that when repeating the test, I get the same situation you have.

The developers have accepted this situation (from some.java.class import * not working) as a bug.

I will document it in the bug tracker.

Revision history for this message
eliteSKL (camaro70s) said :
#6

I can't help with the java path bug thingy.... but this will get you a screen shot.... i used this as part of an error process for scripts that i run. so i can see what happens when they crash. don't know if this helps or not.

import os
import getpass
import shutil

pathtosavefile=os.path.join(r"C:\Documents and Settings", getpass.getuser(), "Desktop") #save to desktop

shutil.move(capture(SCREEN), pathtosavefile) #put this as part of your except statements.