Execution of Python code with -m option or not
Question: 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?


Answer: When you use the [`-m` command-line
flag](http://docs.python.org/2/using/cmdline.html#cmdoption-m), 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 bin/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
a regular module. A new module object is created to hold the global namespace,
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 and have that run when
running `python -m package_name`; in fact that's 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. It's name is
then still set to `__main__`, and the module object is still stored in
`sys.modules['__main__']`.

