Search code examples
pythonpython-3.xpython-dataclasses

How does one ignore extra arguments passed to a dataclass?


I'd like to create a config dataclass in order to simplify whitelisting of and access to specific environment variables (typing os.environ['VAR_NAME'] is tedious relative to config.VAR_NAME). I therefore need to ignore unused environment variables in my dataclass's __init__ function, but I don't know how to extract the default __init__ in order to wrap it with, e.g., a function that also includes *_ as one of the arguments.

import os
from dataclasses import dataclass

@dataclass
class Config:
    VAR_NAME_1: str
    VAR_NAME_2: str

config = Config(**os.environ)

Running this gives me TypeError: __init__() got an unexpected keyword argument 'SOME_DEFAULT_ENV_VAR'.


Solution

  • I would just provide an explicit __init__ instead of using the autogenerated one. The body of the loop only sets recognized value, ignoring unexpected ones.

    Note that this won't complain about missing values without defaults until later, though.

    import dataclasses
    
    @dataclasses.dataclass(init=False)
    class Config:
        VAR_NAME_1: str
        VAR_NAME_2: str
    
        def __init__(self, **kwargs):
            names = set([f.name for f in dataclasses.fields(self)])
            for k, v in kwargs.items():
                if k in names:
                    setattr(self, k, v)
    

    Alternatively, you can pass a filtered environment to the default Config.__init__.

    field_names = set(f.name for f in dataclasses.fields(Config))
    c = Config(**{k:v for k,v in os.environ.items() if k in field_names})