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
