Home > front end >  How to use the settings package's `--settings` when using ArgParse?
How to use the settings package's `--settings` when using ArgParse?

Time:12-21

Background:
Python has a simple_settings [package][1] which allows easy import of program settings from an external file. A program someone wrote, used to supply the settings to the program from the commandline as python prog.py --settings=someFolder.settings, and the settings.py file would be located in ./someFolder. The person who wrote it, didn't use any argument parser. The --settings argument was just detected by the simple_settings package.

Problem that started:
But when I started using [argparse][2], I was forced by argparse to introduce this line parser.add_argument("-s", "--settings", help="To enter the settings to be used. Use as python3 thisProg.py --settings=somefolder.settings"). Else it'd throw an error that --settings is unrecognized.

Problem is, now simple_settings cannot find the --settings flag anymore. I get an error when I try to access any settings stored in the settings.py file.

  File "run.py", line 8, in <module>
    from prog import app_logger
  File "/home/user/project/prog/app_logger.py", line 17, in <module>
    prog_fh = logging.FileHandler(settings.LOG_FILE)
  File "/home/user/.local/lib/python3.8/site-packages/simple_settings/core.py", line 95, in __getattr__
    self.setup()
  File "/home/user/.local/lib/python3.8/site-packages/simple_settings/core.py", line 69, in setup
    self._load_settings_pipeline()
  File "/home/user/.local/lib/python3.8/site-packages/simple_settings/core.py", line 76, in _load_settings_pipeline
    strategy = self._get_strategy_by_file(settings_file)
  File "/home/user/.local/lib/python3.8/site-packages/simple_settings/core.py", line 92, in _get_strategy_by_file
    raise RuntimeError('Invalid settings file [{}]'.format(settings_file))
RuntimeError: Invalid settings file [someFolder.settings]  

How I tried solving it:
Wrote a small program to emulate argv, but it seems to be the wrong way to do it and does not work.

from argparse import ArgumentParser
from simple_settings import settings

if __name__ == '__main__':
    parser = ArgumentParser()
    parser.add_argument("-d", "--desk", help="To enter the desk ID. Use as `python3 thisProg.py -d=<ID>`")
    parser.add_argument("-s", "--settings", help="To enter the settings to be used. Use as `python3 thisProg.py --settings=somefolder.settings`")
    args = parser.parse_args()             
    argv = []   
    argv.append(f"--settings={args.settings}")
    serv = settings.RT_SERVICE,
    sec = settings.CACHE_DATA_EXPIRY_SECONDS

settings.py

RT_SERVICE = 'rt'
CACHE_DATA_EXPIRY_SECONDS = 260
LOG_FILE = 'somefile.log'

Question:
What is the right way to supply the settings to the simple_settings program?
[1]: https://pypi.org/project/simple-settings/ [2]: https://docs.python.org/3/library/argparse.html

CodePudding user response:

The documentation for simple_settings says that you can create your own instance of LazySettings instead of the (pre-made) instance settings.

from simple_settings import LazySettings


settings = LazySettings("settings.development")

Instead of you calling LazySettings explicitly, we'll let the argparse parser do it for you, using the setting argument's type keyword argument.

from argparse import ArgumentParser
from simple_settings import LazySettings

if __name__ == '__main__':
    parser = ArgumentParser()
    parser.add_argument("-d", "--desk")
    parser.add_argument("-s", "--settings", type=LazySettings)
    args = parser.parse_args()

    serv = args.settings.RT_SERVICE,
    sec = args.settings.CACHE_DATA_EXPIRY_SECONDS

Whatever option you pass on the command line, parse_args will call LazySettings on it and assign the resulting value to the settings attribute of the Namespace object it will return.

CodePudding user response:

It sounds like both argparse and simple_settings consume your arguments in their entirety, so that might be an either/or choice unless you want to hack around it. In order to continue using the simple_settings package, it looks like you could take --settings as an argument in your arg parser, then pass that argument to instantiate to LazySettings, which instantiates your settings in the same way, but from within your script.

Here is what works on my machine...

script.py:

from simple_settings import LazySettings
from argparse import ArgumentParser

if __name__ == '__main__':
    parser = ArgumentParser()
    parser.add_argument("-s", "--settings", help="To enter the settings to be used. Use as `python3 thisProg.py --settings=somefolder.settings`")
    args = parser.parse_args()             
    settings = LazySettings(args.settings)
    print(settings)

foo_settings.py:

FOO_SETTING = True

Command line:

% python3 script.py --settings foo_settings
<SIMPLE-SETTINGS ({'FOO_SETTING': True})>

Link to simple_settings repo which mentions LazySettings in this section

  • Related