0

Say I'm storing settings in a Python file, like so:

#!/usr/bin/env python
#
# settings.py

import os

LOG_DIR = '/tmp'
LOG_FILE_MAIN = os.path.join(LOG_DIR, 'main.log')

Now, I include that file like so and change one of the values:

#!/usr/bin/env python
#
# main.py

import settings

settings.LOG_DIR = '/home/myuser'

When I print out a variable that relies on a (now changed) "reference" variable, I'll see that the value hasn't changed.

print(settings.LOG_FILE_MAIN)

Will return:

/tmp/main.log

Instead of:

/home/myuser/main.log

I understand why this is (Python has already calculated the strings value), but I need to work around it. Is there a way to achieve the desired result, other than creating a class and overriding the __setattr__ function?

stephenfin
  • 1,447
  • 3
  • 20
  • 41

1 Answers1

1

Python has already executed the expression setting LOG_FILE_MAIN, and won't set it again just because you changed one of the inputs. The result of the expression is stored, not the expression itself.

You'll have to manually set the other variable again, or calculate it with a function at a later point, provided it is always to be calculated from LOG_DIR. E.g. LOG_FILE_MAIN should not be part of your settings, but always be calculated from settings as needed. I prefer low-tech approaches like that over the alternatives, which do require you to override the __setattr__ function, or otherwise handle all key attributes as setters.

Another approach is to use formatting operations; define LOG_FILE_MAIN as a string that'll have the whole settings module applied as keyword arguments in a str.format() call:

LOG_FILE_MAIN = '{LOG_DIR}/main.log'

and then every time you need to use LOG_FILE_MAIN do:

settings.LOG_FILE_MAIN.format(**vars(settings))

optionally applying a dir separator translation step to that too to make it platform-specific.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343