blueFast
blueFast

Reputation: 44381

Convert module to dict

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?

EDIT

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

Answers (6)

RomanIz
RomanIz

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

Amae Saeki
Amae Saeki

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

hs moon
hs moon

Reputation: 161

import inspect
from itertools import takewhile

import .settings

dict(takewhile(lambda i: i[0] != '__builtins__', inspect.getmembers(settings)))

Upvotes: 2

Siyu
Siyu

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

tna0y
tna0y

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

heykarimoff
heykarimoff

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

Related Questions