pn1 dude
pn1 dude

Reputation: 4402

Print a variables value in a module

I have a lot of constant variables in my application. In this application I import a module. As part of testing I would like to call from a function in said imported module that prints out the variable's name and their values.

OK so this is not my code but this shows the concept of what I would like to do:

-main.py-
import mymodule
DEBUG = True
BATCH = False
ShowVars(['DEBUG','BATCH'])

-mymodule.py-
def ShowVars(varlist):
  for name in varlist:
    print('{} -> {}').format(name,eval(name))

I get at error at the eval(name) that 'DEBUG is not defined' of course but I am trying to get this concept working.

One way I found is to change main.py as:

-main.py-
import mymodule
DEBUG = True
BATCH = False
mymodule.DEBUG=DEBUG
mymodule.BATCH=BATCH
ShowVars(['DEBUG','BATCH'])

Then things work but I'm not sure I like it... Any ideas or anecdotes would be appreciated.

Upvotes: 0

Views: 1674

Answers (4)

pn1 dude
pn1 dude

Reputation: 4402

Thanks to all that answered! Your insight got me going down a long path. I tried using all the techniques and found that the inspect module did what I needed. But as I worked on implementing that into our real code I found that where I was in the frame stack was going to be important. I was able to accomplish that with the inspect module by using multiple .f_backs but I ultimately went with sys._getframe() because you can give it a depth. So my original mymodule.py was changed to:

-mymodule.py-
import sys
import traceback

def ShowVars(varlist):
  depth = len(traceback.extract_stack())-1
  f = sys._getframe(depth)
  for name in varlist:
    print('{} -> {}').format(name,f.f_locals.get(name,f.f_globals.get(name)))

Upvotes: 0

falsetru
falsetru

Reputation: 369064

Using inspect module:

import inspect

def ShowVars(varlist):
    frame = inspect.currentframe().f_back
    g = frame.f_globals
    l = frame.f_locals
    for name in varlist:
        print('{} -> {}'.format(name, l.get(name, g.get(name))))

ALTERNATIVE

main.py:

import mymodule
DEBUG = True
BATCH = False
mymodule.ShowVars(DEBUG, BATCH)

mymodule.py:

import inspect

def ShowVars(*values):
    line = inspect.stack()[1][4][0]
    names = line.rsplit('(', 1)[-1].split(')', 1)[0] # Extract argument names.
    names = map(str.strip, names.split(','))
    for name, value in zip(names, values):
        print('{} -> {}'.format(name, value))

Upvotes: 2

Katsu
Katsu

Reputation: 1958

Import inside function is not pretty but it works:

-main.py-

from mymodule import *
DEBUG = True
BATCH = False

if __name__ == '__main__':
  ShowVars(['DEBUG','BATCH'])

-mymodule.py-

def ShowVars(varlist):
  from main import *
  for name in varlist:
    print('{} -> {}').format(name,eval(name))

Upvotes: 1

Steve Barnes
Steve Barnes

Reputation: 28370

members = dir(module)
for item in members:
   if not eval('hasattr(module.%s, "__call__")' % item):
      print item, eval("module.%s" % item)

Should give you a first pass but you might wish to filter out things that start with _ and other items.

Upvotes: 1

Related Questions