Search code examples
pythonmodulechaining

python chaining modules execution


I do have the situation as follows:

main.py
moduleA.py
moduleB.py

moduleA contains main() function
moduleB contains main() function

I do in main:

import moduleA, moduleB

def main():
    moduleA.main()
    moduleB.main()

if __name__ == '__main__':
    main()

I wonder if I can chain modules execution:

import moduleA, moduleB

def main():
    moduleA().moduleB()

if __name__ == '__main__':
    main()

is it achievable? I know the code above will not work because the modul is not callable.


Solution

  • You can make modules callable if you really wish to.

    Christoph Böddeker has outlined a solution that adds the __call__ magic method to a subclass of types.ModuleType and assigns this class to the module. This answer is based on Alex Martelli's approach of replacing the actual module in sys.modules by a callable class instance that calls the method in question. The latter solution shadows all content of the module that has not been added to the class while the former solution maintains a module's behavior and the exposure of the items contained within.

    Translated to your requirement, Christoph's solution would look like this:

    moduleA.py and moduleB.py

    import sys
    
    class MyModule(sys.modules[__name__].__class__):
        def __call__(self):
            self.main() # call your main function here
    
    sys.modules[__name__].__class__ = MyModule
    
    
    def main():
        "do your stuff"
    

    main.py

    import moduleA, moduleB
    
    def main():
        moduleA()
        moduleB()
    
    if __name__ == '__main__':
        main()
    

    However, I would advise against doing so.

    1. I consider this a violation of the princible of least astonishment.
    2. Implementing either approach on every module you want to be callable is arguably more work than simply calling moduleA.main() explicitly