Reputation: 44381
I would like to do the following (python3):
In module settings.py
:
message = 'Hello'
In module __main__.py
:
from . import settings
def dict_from_module(module):
...
return d
print(dict_from_module(settings))
Running this should produce:
{'message': 'hello'}
Is there a canonical way of converting a module to a dictionary?
Using vars(settings)
gives lots of internal information:
{
'__builtins__': {
...
},
'__cached__': 'xxx/__pycache__/settings.cpython-34.pyc',
'__doc__': None,
'__file__': 'xxx/settings.py',
'__loader__': <_frozen_importlib.SourceFileLoader object at 0x7f87fc192518>,
'__name__': 'xxx.settings',
'__package__': 'xxx',
'__spec__': ModuleSpec(...),
'message': 'bye'
}
Which I do not want / need. I can filter that out (by removing keys starting with __
), but I would like to avoid hacking around if there is an accepted way of doing this.
Upvotes: 10
Views: 9306
Reputation: 1
if settings.py
content variable only:
settings.py:
var1 = 'val1'
var2 = 2
main.py:
from pprint import pprint
import settings
v={var:vars(settings)[var] for var in dir(settings) if not var.startswith('_')}
pprint(v)
{'var1': 'val1',
'var2': 2}
Upvotes: 0
Reputation: 119
This is improved @heykarimoff answer, that I personally use.
# firstly I make a class attribute dict
class Ad(dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__dict__ = self
# and now I make this function:
def m2d(module):
return Ad({val: getattr(module, val) for val in dir(module) if '__' not in val})
import myModule
myDict = m2d(myModule) #our dictionary
As a result i receive a dictionary that acts like a module. In opposite to a module though you can pass it easily to functions avoiding "Can't pickle module objects" error. Hope it helps!
Upvotes: 0
Reputation: 161
import inspect
from itertools import takewhile
import .settings
dict(takewhile(lambda i: i[0] != '__builtins__', inspect.getmembers(settings)))
Upvotes: 2
Reputation: 12099
I'm using a python file as a config file where I have constants and computable properties. And to interface with some web service I need it to be serializable (eg like a dictionary). Based on @heykarimoff 's solution, I used startswith("_")
and isinstance(v, ModuleType):
to filter out imported modules so that they won't show up in the dictionary.
def dict_from_module(module):
context = {}
for setting in dir(module):
if not setting.startswith("_"):
v = getattr(module, setting)
if not isinstance(v, ModuleType):
context[setting] = getattr(module, setting)
return context
Upvotes: 1
Reputation: 1942
Anothoer option is to use __all__
with module you with to convert to dict.
For example, my exported module is
# mylib.py
__all__ = ['square']
def square(x):
return x ** 2
And you can easily convert this module to dict like this:
def module_to_dict(module):
return {key: getattr(module, key) for key in module.__all__}
Giving the following output:
>>> import mylib
>>> module_to_dict(mylib)
{'square': <function square at 0x03C39B28>}
Upvotes: 4
Reputation: 739
Hope this helps!
def dict_from_module(module):
context = {}
for setting in dir(module):
# you can write your filter here
if setting.islower() and setting.isalpha():
context[setting] = getattr(module, setting)
return context
Upvotes: 10