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__'].
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__'].
Execution of Python code with -m option or not
Use the -m flag.
The results are pretty much the same when you have a script, but when you develop a package, without the -m flag, there's no way to get the imports to work correctly if you want to run a subpackage or module in the package as the main entry point to your program (and believe me, I've tried.)
The docs
Like the docs on the -m flag say:
Search sys.path for the named module and execute its contents as the
__main__module.
and
As with the -c option, the current directory will be added to the start of sys.path.
so
python -m pdb
is roughly equivalent to
python /usr/lib/python3.5/pdb.py
(assuming you don't have a package or script in your current directory called pdb.py)
Explanation:
Behavior is made "deliberately similar to" scripts.
Many standard library modules contain code that is invoked on their execution as a script. An example is the timeit module:
Some python code is intended to be run as a module: (I think this example is better than the commandline option doc example)
$ python -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 3: 40.3 usec per loop
$ python -m timeit '"-".join([str(n) for n in range(100)])'
10000 loops, best of 3: 33.4 usec per loop
$ python -m timeit '"-".join(map(str, range(100)))'
10000 loops, best of 3: 25.2 usec per loop
And from the release note highlights for Python 2.4:
The -m command line option - python -m modulename will find a module in the standard library, and invoke it. For example,
python -m pdbis equivalent topython /usr/lib/python2.4/pdb.py
Follow-up Question
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".
It means any module you can lookup with an import statement can be run as the entry point of the program - if it has a code block, usually near the end, with if __name__ == '__main__':.
-m without adding the current directory to the path:
A comment here elsewhere says:
That the -m option also adds the current directory to sys.path, is obviously a security issue (see: preload attack). This behavior is similar to library search order in Windows (before it had been hardened recently). It's a pity that Python does not follow the trend and does not offer a simple way to disable adding . to sys.path
Well, this demonstrates the possible issue - (in windows remove the quotes):
echo "import sys; print(sys.version)" > pdb.py
python -m pdb
3.5.2 |Anaconda 4.1.1 (64-bit)| (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)]
Use the -I flag to lock this down for production environments (new in version 3.4):
python -Im pdb
usage: pdb.py [-c command] ... pyfile [arg] ...
etc...
from the docs:
-IRun Python in isolated mode. This also implies -E and -s. In isolated mode sys.path contains neither the script’s directory nor the user’s site-packages directory. All PYTHON* environment variables are ignored, too. Further restrictions may be imposed to prevent the user from injecting malicious code.
What does __package__ do?
It enables explicit relative imports, not particularly germane to this question, though - see this answer here: What's the purpose of the "__package__" attribute in Python?
What is -m? Specifically in "python -m pip install...."
What is the -m flag's purpose?
What does -m flag do when running a python scripts.
python -m flag
The -m flag searches your shell PATH for module and runs the contents, typically the __main__.py file. You typically would not run a file as a module, such as the example you included. Instead, if you ever install a package via pip, then want to execute it via CLI instead of through another python script, you can invoke it via this -m flag. I hope this helps clear up some misconceptions you may have.
Here are some of the relevant docs which explain this better than I do.
[Python -m docs]
[Python __main__ docs
More on reddit.comVideos
Despite this question having been asked and answered several times (e.g., here, here, here, and here), in my opinion no existing answer fully or concisely captures all the implications of the -m flag. Therefore, the following will attempt to improve on what has come before.
Introduction (TLDR)
The -m flag does a lot of things, not all of which will be needed all the time. In short, it can be used to: (1) execute Python code from the command line via modulename rather than filename (2) add a directory to sys.path for use in import resolution and (3) execute Python code that contains relative imports from the command line.
Preliminaries
To explain the -m flag we first need to explain a little terminology.
Python's primary organizational unit is known as a module. Modules come in one of two flavors: code modules (aka modules) and package modules (aka packages; packages are a type of module). A code module is any file that contains Python executable code. A package module is any directory that contains other modules (either code modules or package modules). The most common type of code module is a *.py file while the most common type of package module is a directory containing an __init__.py file.
Python allows modules to be uniquely identified in two ways: modulename and filename. In general, modules are identified by modulename in Python code (e.g., import <modulename>) and by filename on the command line (e.g., python <filename>). All Python interpreters are able to convert modulenames to filenames by following the same few, well-defined rules. These rules hinge on the sys.path variable. By altering this variable one can change how Python resolves modulenames into filenames (for more on how this is done see PEP 302).
All modules (both code and package) can be executed (i.e., code associated with the module will be evaluated by the Python interpreter). Depending on the execution method (and module type) what code gets evaluated, and when, can change quite a bit. For example, if one executes a package module via python <filename> then <filename>/__main__.py will be executed. On the other hand, if one executes that same package module via import <modulename> then only the package's __init__.py will be executed.
Historical Development of -m
The -m flag was first introduced in Python 2.4.1. Initially its only purpose was to provide an alternative means of identifying the Python module to execute from the command line. That is, if we knew both the <filename> and <modulename> for a module then the following two commands were equivalent: python <filename> <args> and python -m <modulename> <args>. One constraint with this iteration, according to PEP 338, was that -m only worked with top level modulenames (i.e., modules that could be found directly on sys.path without any intervening package modules).
With the completion of PEP 338 the -m feature was extended to support <modulename> representations beyond the top level. This meant names such as http.server were now fully supported. This extension also meant that each parent package in modulename was now evaluated (i.e., all parent package __init__.py files were evaluated) in addition to the module referenced by the modulename itself.
The final major feature enhancement for -m came with PEP 366. With this upgrade -m gained the ability to support not only absolute imports but also explicit relative imports when executing modules. This was achieved by changing -m so that it set the __package__ variable to the parent module of the given modulename (in addition to everything else it already did).
Use Cases
There are two notable use cases for the -m flag:
To execute modules from the command line for which one may not know their filename. This use case takes advantage of the fact that the Python interpreter knows how to convert modulenames to filenames. This is particularly advantageous when one wants to run stdlib modules or 3rd-party module from the command line. For example, very few people know the filename for the
http.servermodule but most people do know its modulename so we can execute it from the command line usingpython -m http.server.To execute a local package containing absolute or relative imports without needing to install it. This use case is detailed in PEP 338 and leverages the fact that the current working directory is added to
sys.pathrather than the module's directory. This use case is very similar to usingpip install -e .to install a package in develop/edit mode.
Shortcomings
With all the enhancements made to -m over the years it still has one major shortcoming -- it can only execute modules written in Python (i.e., *.py). For example, if -m is used to execute a C compiled code module the following error will be produced, No code object available for <modulename> (see here for more details).
Detailed Comparisons
Module execution via import statement (i.e., import <modulename>):
sys.pathis not modified in any way__name__is set to the absolute form of<modulename>__package__is set to the immediate parent package in<modulename>__init__.pyis evaluated for all packages (including its own for package modules)__main__.pyis not evaluated for package modules; the code is evaluated for code modules
Module execution via command line with filename (i.e., python <filename>):
sys.pathis modified to include the final directory in<filename>__name__is set to'__main__'__package__is set toNone__init__.pyis not evaluated for any package (including its own for package modules)__main__.pyis evaluated for package modules; the code is evaluated for code modules.
Module execution via command line with modulename (i.e., python -m <modulename>):
sys.pathis modified to include the current directory__name__is set to'__main__'__package__is set to the immediate parent package in<modulename>__init__.pyis evaluated for all packages (including its own for package modules)__main__.pyis evaluated for package modules; the code is evaluated for code modules
Conclusion
The -m flag is, at its simplest, a means to execute python scripts from the command line by using modulenames rather than filenames. The real power of -m, however, is in its ability to combine the power of import statements (e.g., support for explicit relative imports and automatic package __init__ evaluation) with the convenience of the command line.
The first line of the Rationale section of PEP 338 says:
Python 2.4 adds the command line switch
-mto allow modules to be located using the Python module namespace for execution as scripts. The motivating examples were standard library modules such aspdbandprofile, and the Python 2.4 implementation is fine for this limited purpose.
So you can specify any module in Python's search path this way, not just files in the current directory. You're correct that python mymod1.py mymod2.py args has exactly the same effect. The first line of the Scope of this proposal section states:
In Python 2.4, a module located using
-mis executed just as if its filename had been provided on the command line.
With -m more is possible, like working with modules which are part of a package, etc. That's what the rest of PEP 338 is about. Read it for more info.
I've only used -m when instructed to do so and Googling this didn't bring up anything. What is -m?
I noticed it's provided in the example when creating a virtual environment and it's necessary in some applications.
Man pages says: "Searches sys.path for the named module and runs the corresponding .py file as a script."
When would I need to use " -m " and what does it actually do?
What actually happens when python imports a package using python -m flag? Does it bring the module into your current directory?
For instance, what is the difference between python hello.py vs python -m hello.py.
I tried reding it up on sites like quora, but I didn't really understand the explanations all too well.
The -m flag searches your shell PATH for module and runs the contents, typically the __main__.py file. You typically would not run a file as a module, such as the example you included. Instead, if you ever install a package via pip, then want to execute it via CLI instead of through another python script, you can invoke it via this -m flag. I hope this helps clear up some misconceptions you may have.
Here are some of the relevant docs which explain this better than I do.
[Python -m docs]
[Python __main__ docs
As u/jarulsamy said, it's a way you can run a CLI interface to a module, instead of importing it and writing your own code to use it.
If you just give it a package name (eg, rich, requests), then it will find that package and run the __main__.py file in that package. But if you give it an actual script name, it will run that script as if you'd just run it directly.
A good example is the Rich module's "demo" feature. For example, you could read the doco on rich.prompt and write your own code; or just run python -m rich.prompt from the CLI and see the author's example / demo. The -m there is basically finding "rich" in your system path (which would be your local Python site library / virtual environment) and then running the "prompt.py" code there as the main script.
So, instead of having to type python /really/long/system/path/you/wont/remember/rich/prompt.py, Python does the work for you and finds the Rich module in your path.