-1

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.

mothership
  • 43
  • 8
  • 1
    The syntax for "chaining" the execution of two functions is exactly what you're already doing with `moduleA.main()` and `moduleB.main()` on successive lines. – user2357112 Jun 26 '18 at 08:34
  • @user2357112 please repost your comment as an answer – bruno desthuilliers Jun 26 '18 at 08:41
  • yeah, but it is about avoiding using moduleA.main() and simply doing moduleA() but using some magic e.g. if __name__ == '__main__' in each module ... are there any python tricks which could help me doing so? – mothership Jun 26 '18 at 08:51

1 Answers1

1

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
shmee
  • 4,721
  • 2
  • 18
  • 27