0

I am trying to create a logger function:

def logger(someVariable): 
    # some code that prints the name of someVariable 

So when I call the function:

logger(myvarA)        # should output the string 'myvarA'
logger(someobj.varB)  # should output the string 'someobj.varB'
logger(myarr[3])      # should (probably) output 'myarr[3]'

Not sure if all or even any of these cases are possible? The use case for this is to have a simple function in iPython Notebook to log any variables for their values without having to type something like below:

logger(myVarA,'myVarA')
logger(myarr[i],'myarr[{}]'.format(i))
Pan Yan
  • 1,572
  • 1
  • 13
  • 21
  • 1
    There is a way, but it's extremely hacky, and this is almost certainly an [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – TigerhawkT3 Jul 29 '15 at 02:02
  • I described the use case: how to log variable values without having to pass the variable name explicitly? The described "logger" is supposed to save a variable name and its value into a file or print onto console. – Pan Yan Jul 29 '15 at 02:41
  • This and similar questions have been answered already, for example see http://stackoverflow.com/questions/582056/getting-list-of-parameter-names-inside-python-function. –  Jul 29 '15 at 03:47
  • @TrisNefzger, thanks, but not really. That solution show the argument list names, but I want to get caller side argument name. (i.e., the feeding variable name). – Pan Yan Jul 29 '15 at 04:03

1 Answers1

1

The inspect module (https://docs.python.org/3/library/inspect.html#inspect.getframeinfo) will also give you the code context. You simply need to parse that to get the text of what was passed. With only a single variable, it's pretty easy to do. Here's a sample.

import inspect
import re

def handle_nested_parens(v):
   parens = 0
   output = ""
   for c in v:
       if c == ")":
           parens = parens - 1
           if parens < 0:
               return output
       output += c
       if c == "(":
           parens = parens + 1
   return output

def logger(v):
   currentframe = inspect.currentframe()
   code_context = inspect.getouterframes(currentframe,1)[1][4][0]
   variable = handle_nested_parens(re.sub(r".*logger\((.*)",r"\1", code_context))
   print("{0} => {1}".format(variable, v))


def testing(a):
   return(a)

def submain(a):
   ab = (1, 2, a)
   logger(testing(ab))
   return 15

def main():
   xyz = "hello"
   logger(xyz)
   logger(submain(xyz))


if __name__ == '__main__':
    a = 5
    logger(a)
    main()

It outputs

a => 5
xyz => hello
testing(ab) => (1, 2, 'hello')
submain(xyz) => 15
clockwatcher
  • 2,904
  • 10
  • 10