59

Let's assume I have the following file structure:

data.py

foo = []
bar = []
abc = "def"

core.py

import data
# do something here #
# a = ...
print a
# ['foo', 'bar', 'abc']

I need to get all the variables defined in data.py file. How can I achieve that? I could use dir(), but it returns all the attributes of the module including __name__ and so on.

4
  • 3
    I think dir() is exactly how I would do it; just skip anything that looks like "not a variable": print [v for v in dir(data) if not v.startswith('__')] Commented Mar 18, 2012 at 16:11
  • 4
    Keep data out of your variable names. Commented Mar 18, 2012 at 16:11
  • You could use dir() and skip all variables starting with __. Commented Mar 18, 2012 at 16:12
  • I need to to import data from my existing project which is no longer supported and transfer the data to the DB. Commented Mar 18, 2012 at 16:12

9 Answers 9

78
print [item for item in dir(adfix) if not item.startswith("__")]

Is usually the recipe for doing this, but it begs the question.

Why?

Sign up to request clarification or add additional context in comments.

10 Comments

And why not? Because explicit is better than implicit?
Why - e.g. a module contains errorcodes in variables (imagine a python wrapper round C enums), adding all the values and error names to a dict for useful error reporting.
Putting test data to a separate module and importing them all for automated testing with fixtures. So for a new dataset to test, you just put it in that module and the test framework will pick it up automatically.
There are demonstrably valid reasons for doing this, especially when handling third-party APIs under foreign control. Numpy is the canonical example here. The numpy.distutils.__config__ API only provides machine-generated dictionary globals rather than human-usable callables. How does one query this abominable API? dir(), hasattr(), and getattr(), of course. Whenever the Pythonisticity of a question is questioned, I sagely roll my eyes. A non-Pythonic solution considered harmful in the common case may prove to be the only solution in edge cases. Welcome to the real world.
I needed it in debugging my own code. There should have been a global variable but python kept showing 'module' object has no attribute 'variable'. Using that showed that the variable was cached with the previous name.
|
19
#!/usr/local/bin/python
# coding: utf-8
__author__ = 'spouk'

def get_book_variable_module_name(module_name):
    module = globals().get(module_name, None)
    book = {}
    if module:
        book = {key: value for key, value in module.__dict__.iteritems() if not (key.startswith('__') or key.startswith('_'))}
    return book

import config

book = get_book_variable_module_name('config')
for key, value in book.iteritems():
    print "{:<30}{:<100}".format(key, value)

example config

#!/usr/local/bin/python
# coding: utf-8
__author__ = 'spouk'

import os

_basedir = os.path.abspath(os.path.dirname(__file__))

# database section MYSQL section
DBHOST = 'localhost'
DBNAME = 'simple_domain'
DBPORT = 3306
DBUSER = 'root'
DBPASS = 'root'

# global section
DEBUG = True
HOSTNAME = 'simpledomain.com'
HOST = '0.0.0.0'
PORT = 3000
ADMINS = frozenset(['admin@localhost'])
SECRET_KEY = 'dfg45DFcx4rty'
CSRF_ENABLED = True
CSRF_SESSION_KEY = "simplekey"

result function

/usr/local/bin/python2 /home/spouk/develop/python/2015/utils_2015/parse_config_py.py
DBPORT                        3306                                                                                                
os                            <module 'os' from '/usr/local/lib/python2.7/os.pyc'>                                                
DBHOST                        localhost                                                                                           
HOSTNAME                      simpledomain.com                                                                                    
HOST                          0.0.0.0                                                                                             
DBPASS                        root                                                                                                
PORT                          3000                                                                                                
ADMINS                        frozenset(['admin@localhost'])                                                                      
CSRF_SESSION_KEY              simplekey                                                                                           
DEBUG                         1                                                                                                   
DBUSER                        root                                                                                                
SECRET_KEY                    dfg45DFcx4rty                                                                                       
CSRF_ENABLED                  1                                                                                                   
DBNAME                        simple_domain                                                                                       

Process finished with exit code 0

Enjoy, dude. :)

1 Comment

Neat solution! In Python 3, use .items() instead of .iteritems()
4

If you need the variable and the value assigned to it then

import data

for name ,values in vars(data).items():
    print(name, values)

You can choose to store name (all the variable names in the script) or the value attached to it .

Comments

3

This is the version I wrote for python 3.7 (it excludes the internal dunder methods via the condition in the comprehension)

print([v for v in dir(data) if v[:2] != "__"])

A longer but complete working example is below:

"""an example of a config file whose variables may be accessed externally"""
# Module variables
server_address = "172.217.167.68"
server_port = 8010
server_to_client_port = 8020
client_to_server_port = 8030
client_buffer_length = 4096
server_buffer_length = 2048

def printVariables(variable_names):
    """Renders variables and their values on the terminal."""
    max_name_len = max([len(k) for k in variable_names])
    max_val_len = max([len(str(globals()[k])) for k in variable_names])

    for k in variable_names:
        print(f'  {k:<{max_name_len}}:  {globals()[k]:>{max_val_len}}')

if __name__ == "__main__":
    print(__doc__)
    ks = [k for k in dir() if (k[:2] != "__" and not callable(globals()[k]))]
    printVariables(ks)

The above code outputs:

an example of a config file whose variables may be accessed externally
  client_buffer_length :            4096
  client_to_server_port:            8030
  server_address       :  172.217.167.68
  server_buffer_length :            2048
  server_port          :            8010
  server_to_client_port:            8020

Comments

3

I have to make a dictionary of these variables. I used this code.

print({item:getattr(my_module, item) for item in dir(my_module) if not item.startswith("__") and not item.endswith("__")})

1 Comment

Very useful! It gets the actual variables, and not just their names. I was hoping for a builtin to get these, but it looks like we have to manually check to make sure the properties don't begin and end with '__'!
2

I offer my solution. It is convenient in that it allows you to display variables from any imported module.

If you do not specify the name of the module, then the list of variables of the current module is displayed.

import sys

def print_settings(module_name=None):
    module_name = sys.modules[__name__] if not module_name else module_name
    variables = [
        (key, value)
        for (key, value) in vars(module_name).items()
        if (type(value) == str or type(value) == int or type(value) == float)
        and not key.startswith("_")
    ]

    for (key, value) in variables:
        print(f"{key: <20}  {value}")

Comments

0

Here's a roundabout way, if you prefer to be more explicit:

data.py

a = [
  foo := [],
  bar := [],
  abc := "def",
]

core.py

import data

print(data.foo)
print(data.a)

Comments

0

To get list of specific variables or functions names in module You can try a following lambda

# DIR modification 
fvdir = lambda d,s="",w="__": [v for v in dir(vars(d).items()) if s in v and not w in v]
ffdir = lambda d,s="",w="__": [v for v in dir(d) if s in v and not w in v]
ffvdir = lambda d,s="",w="__": [v for v in (dir(d)+dir(vars(d).items())) if s in v and not w in v]

print( fvdir( os, "", "*") ) # this will print all vars in os including __
print( fvdir( os, "sub", "class") ) # this will print vars in os that contain sub and not contain class subwords

fvdir(d, s, w) - stays for find variable in dir of module d, with name filter s and not w

ffdir(d, s, w) - stays for find function in dir of module d, with name filter s and not w

ffvdir(d, s, w) - stays for find function or variable in dir of module d, with name filter s and not w

in many cases You will find handy to use string conversion upper case as below

fvdir = lambda d,s="",w="__": [v for v in dir(vars(d).items()) if s.upper() in v.upper() and not w.upper() in v.upper()]

all above return list so finally more complex search can be done

print( ffdir( os, "sub") + fvdir( os, "g", "*") )

Comments

-3

Try:

for vars in dir():
 if vars.startswith("var"):
   print vars

1 Comment

Doesn't work when i tested it. I think you meant to do dir(data), even then it still does not work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.