I’m using the foo module which includes a few module level variables that dictate its behavior. One of these variables is SANITIZE.
I want to be able to use foo in two ways, foo.parse() and foo2.parse(), where the only difference is foo has SANITIZE=false and foo2 has SANITIZE=true
I want to do this while not having to copy paste my code. For example
#foo module
SANITIZE='foo'
def parse():
print SANITIZE
#foo2 module
import foo
foo.SANITIZE='foo2'
#test script
import foo
import foo2
foo2.foo.parse() #i want this to print 'foo2'
foo.parse() #i want this to print 'foo'
However, the above example will print ‘foo2’ both times. Is there a way to achieve this behavior?
Thanks!
If this is your code, than the solution is not to depend in module level variables, but in some other way to keep state of the objects. Modules in Python are “singletons” – which means that once imported by any module, there is just one version of then, interpreter wide –
The behavior you want, for example, is exactly what you get, for free, if you use class inheritance – the child class can customize some, but no need to rewrite all, of the parent class.
So, if you as much as encapsulate your “foo” code inside a class – you may not even have to write a class that needs instances, you get the features you want already:
Of course, with the cheer amount of introspection and metaprogramming that Python allows, it would be possible to do something like what you want – but it would complicate matters, for no good. Module variables have most of the same disadvantages that global variables have in C code.
One way to do it is to make “foo” when accessed through foo2 to make the variable changes on the fly, call the function in “foo” and restore the previosu values on exit.
For arbitrary code to be triggered on attribute access of “foo” on the module “foo2”, “foo” has to refer to an object with a “property” attribute —
So, the exa example you wrote would run, in a concurency-unsafe way, btw, very unsafe way, if foo2 is written more or less so:
This creates a “foo” object in module foo2 that when accessed, retrieves any requested attributes from the original “foo” module instead. So “foo2.foo.parse” will get the “foo” parse function – but, perceive the ammount of “hackiness” in this approach – in order to be able to restore the original value in the “foo” module that lives inside the Python interpreter, after the function was fetched from foo2, that function have too, upon returning, restore the values itself. The only way to do so is modifying the function so that it runs additional code when it returns – so it is decorated on the fly by the code above.
I think this example makes clear that having module level configurations is not the way to go in this case, although possible.
EDIT
The O.P. commented:
In reply to that:
Reading this description it may sound as “unfeasable” – but it is easier done than described –
Here follows my “foo2” module that does the above:
This code does exactly what I described – it recreates all function objects in the original module, rebindign the globals dict for each function. It is concurrency safe. There are some corner cases if the to-be clonned module does point to native code classes or functions (they are not of “FunctionType”). If it makes heavy usage of multiple class inheritance, metaclasses,- it miught work, or not.
I tested it with a simple class and it worked fine:
And
Output: