__main__ vs official module name: distinct module instances

Cameron Simpson cs at zip.com.au
Sun Aug 2 05:53:27 CEST 2015


Hi All,

Maybe this should be over in python-ideas, since there is a proposal down the 
bottom of this message. But first the background...

I've just wasted a silly amount of time debugging an issue that really I know 
about, but had forgotten.

I have a number of modules which include a main() function, and down the bottom 
this code:

  if __name__ == '__main__':
    sys.exit(main(sys.argv))

so that I have a convenient command line tool if I invoke the module directly.  
I typically have tiny shell wrappers like this:

  #!/bin/sh
  exec python -m cs.app.maildb -- ${1+"$@"}

In short, invoke this module as a main program, passing in the command line 
arguments. Very useful.

My problem?

When invoked this way, the module cs.app.maildb that is being executed is 
actually the module named "__main__". If some other piece of code imports 
"cs.app.maildb" they get a _different_ instance of the module. In the same 
program! And how did it cause me trouble? I am monkey patching my module for 
debug purposes, and that monkey patcher imports the module by name. So I was 
monkey patching cs.app.maildb, and _not_ patching __main__. And thus not seeing 
any effect from the patch.

I realise that having __name__ == '__main__' at all almost implies this effect.  
I am not sure it needs to.

The Proposal:

What are the implications of modifying the python invocation:

  python -m cs.app.maildb

to effectively do this (Python pseudo code):

  M = importlib.import("cs.app.maildb")
  M.__name__ = '__main__'
  sys.modules['__main__'] = M

i.e. import the module by name, but bind it to _both_ "cs.app.maildb" and 
"__main__" in sys.modules. And of course hack .__name__ to support the standard 
boilerplate.

This would save some confusion when the module is invoked from the python 
command line and also imported by the code; it is not intuitive that those two 
things give you distinct module instances.

Aside from the module's .__name__ being '__main__' even when accessed by the 
code as cs.app.maildb, are there other implications to such a change that would 
break real world code?

Cheers,
Cameron Simpson <cs at zip.com.au>

The reasonable man adapts himself to the world; the unreasonable one persists
in trying to adapt the world to himself.  Therefore all progress depends
on the unreasonable man.        - George Bernard Shaw


More information about the Python-list mailing list