["python","module","package"]
Execution of Python code with -m option or not

The python interpreter has -m module option that "Runs library module module as a script". With this python code a.py: if __name__ == "__main__": print __package__ print __name__ I tested python -m a to get "" <-- Empty String __main__ whereas python a.py returns None <-- None __main__ To me, those two invocation seems to be the same except __package__ is not None when invoked with -m option. Interestingly, with python -m runpy a, I get the same as python -m a with python module compiled to get a.pyc. What's the (practical) difference between these invocations? Any pros and cons between them? Also, David Beazley's Python Essential Reference explains it as "The -m option runs a library module as a script which executes inside the __main__ module prior to the execution of the main script". What does it mean?
When you use the -m command-line flag, Python will import a module or package for you, then run it as a script. When you don't use the -m flag, the file you named is run as just a script. The distinction is important when you try to run a package. There is a big difference between: python foo/bar/baz.py and python -m foo.bar.baz as in the latter case, foo.bar is imported and relative imports will work correctly with foo.bar as the starting point. Demo: $ mkdir -p test/foo/bar $ touch test/foo/__init__.py $ touch test/foo/bar/__init__.py $ cat << EOF > test/foo/bar/baz.py > if __name__ == "__main__": > print __package__ > print __name__ > > EOF $ PYTHONPATH=test python test/foo/bar/baz.py None __main__ $ PYTHONPATH=test python -m foo.bar.baz foo.bar __main__ As a result, Python has to actually care about packages when using the -m switch. A normal script can never be a package, so __package__ is set to None. But run a package or module inside a package with -m and now there is at least the possibility of a package, so the __package__ variable is set to a string value; in the above demonstration it is set to 'foo.bar', for plain modules not inside a package it is set to an empty string. As for the __main__ module, Python imports scripts being run as it would import regular modules. A new module object is created to hold the global namespace and is stored in sys.modules['__main__']. This is what the __name__ variable refers to, it is a key in that structure. For packages, you can create a __main__.py module inside and have that run when running python -m package_name; in fact that is the only way you can run a package as a script: $ PYTHONPATH=test python -m foo.bar python: No module named foo.bar.__main__; 'foo.bar' is a package and cannot be directly executed $ cp test/foo/bar/baz.py test/foo/bar/__main__.py $ PYTHONPATH=test python -m foo.bar foo.bar __main__ So, when naming a package for running with -m, Python looks for a __main__ module contained in that package and executes that as a script. Its name is then still set to '__main__' and the module object is still stored in sys.modules['__main__'].