Printing the name of the function and who called it?

In the process of converting a lot of spaghetti code to organized script modules and multiple functions. One drawback I’ve noticed to this is that sometimes the error messages are truncated and not as helpful or specific as if the script was on the button onAction script. I will just get errors that show a Key I tried access in a dictionary that doesn’t exist, or a type error, but no line number or even what function this occured in. I am trying to mediate that.

What I am looking for is some function I can call in the beginning of other functions so that it will print out the current function and what function called it if possible.

I tried doing it with using the inspect module per this and doing this in a function called from another function

import inspect
print "running " + str(inspect.stack()[1][3]) + " called by " + str(inspect.stack()[2][3])

which just throws me a error like so
image

I assume this has to do with the odd runtime environment Ignition is, java calling python scripts etc and so I’m not sure if there is a python stack to really access like there would be in a traditional all python application.

Is there another way to do this? I would really like a function I could call as the first line of other functions that will just print “Running function (function name), called by (function name)”

You might find inspiration in the PythonAsJavaException class in my later.py script module.

How I would in practice use this?

You’re talking a bout this snippet right ?

#------------
# Java wrapper for Jython exceptions to preserve the python
# stack trace.
#
class PythonAsJavaException(java.lang.Exception):

    @staticmethod
    def fullClassName(cls):
        if cls.__bases__:
            return fullClassName(cls.__bases__[0])+"."+cls.__name__
        return cls.__name__

    def __init__(self, pyexc, tb=None):
        super(PythonAsJavaException, self).__init__(str(pyexc), None, True, True)
        traceElements = []
        if tb is None:
            tb = sys.exc_info()[2]
        while tb:
            code = tb.tb_frame.f_code
            vnames = code.co_varnames
            if vnames and vnames[0] in ('cls', 'self'):
                ref = tb.tb_frame.f_locals[vnames[0]]
                if vnames[0] == 'self':
                    className = fullClassName(ref.__class__)
                else:
                    className = fullClassName(ref)
            else:
                className = '<global>'
            traceElements.append(StackTraceElement(className, code.co_name, code.co_filename, tb.tb_lineno))
            tb = tb.tb_next
        self.setStackTrace(traceElements)

It’s a bit over my head - how could I use implement say in a situation like this for a module lets call barcodes?

def create(data):
    import barcodes
    # something here to print the module.create is running, called by GUI
    barcodes.foo()

def foo():
    # something here to print barcode.foo is runnig, called by create
    x = 1

Now say I ran barcode.create(data) from my GUI, how would I use your class to have printed to the console

running barcode.create called from ? 
running barcode.foo called from barcode.create

You wouldn’t use my class. I said inspiration. I would use python/jython’s exception machinery to generate a traceback. With raise inside a try block, if not directly. The traceback has the information you want. That class is an example of traversing it.

1 Like