Reputation: 4402
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
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
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
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
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