Generate a new object each time a name is imported

Michele Simionato michele.simionato at gmail.com
Fri Aug 7 00:54:25 EDT 2009


On Aug 2, 1:18 pm, Paul Rubin <http://phr...@NOSPAM.invalid> wrote:
> Peter Otten <__pete... at web.de> writes:
> > >>> import sys
> > >>> sys.modules["yadda"] = A()
>
> OMG.... wow.  I bow to you.  But I'm not sure whether that's bowing in
> awe or in terror.

I had to play this kind of tricks on our production code, not so long
ago. Not that I am pride of it, but it was the lesser evil to cope
with a wrong design. The scenario: a large legacy code base
based on the idea of using a Python module to keep configuration
parameters. The idea is fine as long as the parameters are
immutable, but in our case the parameters could be changed.
In theory the parameters should have been set only once,
however in practice this was not guaranteed: every piece
of code could change the parameters at some moment, and things
could get "interesting" to debug.
Throwing away the configuration system was not an option, because
it would have involved changing hundreds of modules, so I set out
for a compromise: the parameters are still mutable, but they
can be changed only once. This was implemented by replacing
the module with a configuration object using custom
descriptors. Here is the code:

$ echo config.py
import sys

class WriteOnce(object):
    "WriteOnce descriptor"
    def __init__(self, default):
        self.default = self.value = default
        self.already_set = False
    def __get__(self, obj, objcls):
        return self.value
    def __set__(self, obj, value):
        if value != self.value and self.already_set:
            raise TypeError('You cannot set twice a write-once
attribute!')
        self.value = value
        self.already_set = True

class Config(object):
    "A singleton to be used as a module"
    parameter = WriteOnce(0)

sys.modules['config'] = Config()

The usage is

>>> import config
>>> config.parameter = 42
>>> config.parameter = 43
Traceback (most recent call last):
   ...
TypeError: You cannot set twice a write-once attribute!

Just to say that there are use cases where replacing modules with
objects may have sense.
Still, a better design would just have passed immutable configuration
objects around
(changing the configuration would mean to create a new object).
Unfortunately there are still a lot a people without a functional
mindset :-(



More information about the Python-list mailing list