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