How to get line number from which a function was called in Sikuli?

Asked by Luis Gonzalez on 2012-04-20

Hello again,

I was wondering if there's a way to get the line number from which a function was called when executing a Sikuli Script. I'm trying to do the following:

def xclick(img):
   if exists(img):
      click(getLastMatch())
   else:
      print '[Error] Image not found: ' + img + ' on line' + FUNC_CALL_LINE_NUMBER
      exit(1)

Is this possible?

Thanks in advance!

Question information

Language:
English Edit question
Status:
Solved
For:
Sikuli Edit question
Assignee:
No assignee Edit question
Solved by:
Luis Gonzalez
Solved:
2012-04-20
Last query:
2012-04-20
Last reply:
2012-04-20

When I read log in IDE console, there is always line number if image not found (or other error happened) and app exited.

Example:

[error] An error occurs at line 381
[error] Error message: Traceback (most recent call last):
 File "C:\Users\RPODOL~1.KIE\AppData\Local\Temp\sikuli-tmp8059622772916110289.py", line 381, in
 on_start() #first sequence of start operations
 File "C:\Users\RPODOL~1.KIE\AppData\Local\Temp\sikuli-tmp8059622772916110289.py", line 59, in on_start

From my and the Sikuli IDE perspective, code you wrote is just unneeded.

Or you can go for try: .... except: ... blocks, see examples here:
http://sikuli.org/docx/region.html#exception-findfailed

using that technique you can output at least problematic image name, I think. But if running a script from IDE, to know error line you have just to read the console.

RaiMan (raimund-hocke) said : #2

Yes is possible by evaluating the stack trace.
But to get it, you first need an exception:

import traceback
def xclick(img):
   if exists(img):
      click(getLastMatch())
   else:
      try: raise TypeError
      except TypeError:
         tb = sys.exc_info()[2]
         tbinfo = traceback.extract_tb(sys.exc_info()[2])
         print tbinfo # should print a list with entries like
         # (filename, line number, function name, some text)
      print '[Error] Image not found: ' + img + ' on line' + LINE_NUMBER
      exit(1)

But in this case, since you are aborting your script, if the image is not found, why not use:

def xclick(img):
     click(img)

if the search fails, the script will be aborted with exception find failed and you get your stack trace and the line numbers.

RaiMan (raimund-hocke) said : #3

@ Roman
LOL, i made a break in between, so you won ;-)

Luis Gonzalez (lgonzalez-s) said : #4

Thank you for your answers! There are two reasons why I wouldn't like to just omit the ELSE clause and let the exception be handled by default.

First, I would like a fancier output that matches the one of a log file I create with all the steps of the execution (I do not run this from the IDE, but from console since this is used for automation purposes).

Second, I want to close the application after an exception is found, since what I do is create a list of scripts and each one of them is a Test Case. So, if the TC fails, I want the application (Internet Explorer) to be closed so that the next TC will have a clean slate to start.

Than being said, I found what I needed using traceback.extract_stack.
def xclick(img):
   if exists(img):
      click(getLastMatch())
   else:
      stack = traceback.extract_stack(limit = 2)
      print '[Error] Image not found: ' + img + ' on line' + str(stack[0][1])
      exit(1)

extract_stack returns a list of tuples, and element number 1 of that tuple corresponds to the line number. When the function is called, position 0 of the list of tuples will contain the return information, including the return line number.

Thanks to both, again, for you help!

Luis Gonzalez (lgonzalez-s) said : #5

Oh, and of course, closeApp(appname) within the ELSE clause :)

RaiMan (raimund-hocke) said : #6

Thanks for the finding and talking about it.