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__'].

Answer from Martijn Pieters on Stack Overflow
Top answer
1 of 3
323

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__'].

2 of 3
59

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 pdb is equivalent to python /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:

-I

Run 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?

🌐
Hyperskill
hyperskill.org › university › python › m-command-in-python
“-m” Command in Python
July 17, 2024 - The -m option was added to Python in version 2.4. Prior, to this addition, modules were executed by providing the file name of the module as an argument to the Python command, which had its restrictions. With the m option, users can execute modules without needing to specify the file extension, ensuring that the module runs in the context and namespace.
Discussions

What is -m? Specifically in "python -m pip install...."
Only tangentially related to your question, but the reason that Google didn't help is that the '-' prefix means to exclude from your search. So wrapping it in quotes (python "-m") will give you the results you were expecting. More on reddit.com
🌐 r/learnpython
65
261
September 8, 2020
What is the -m flag's purpose?
It stands for 'module'. It runs the given module name, in this case the 'venv' module. Here's the documentation on it: https://docs.python.org/3/using/cmdline.html#cmdoption-m These options are called "command line arguments", but it's hard to search for in python because the results are swamped out by answers about how to make command line arguments for your own program, instead of python itself. More on reddit.com
🌐 r/learnpython
10
10
July 25, 2022
What does -m flag do when running a python scripts.
It runs a Python module as a script… More on reddit.com
🌐 r/Python
13
5
May 18, 2022
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.com
🌐 r/learnpython
6
7
July 25, 2022
Top answer
1 of 7
354

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:

  1. 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.server module but most people do know its modulename so we can execute it from the command line using python -m http.server.

  2. 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.path rather than the module's directory. This use case is very similar to using pip 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.path is 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__.py is evaluated for all packages (including its own for package modules)
  • __main__.py is not evaluated for package modules; the code is evaluated for code modules

Module execution via command line with filename (i.e., python <filename>):

  • sys.path is modified to include the final directory in <filename>
  • __name__ is set to '__main__'
  • __package__ is set to None
  • __init__.py is not evaluated for any package (including its own for package modules)
  • __main__.py is evaluated for package modules; the code is evaluated for code modules.

Module execution via command line with modulename (i.e., python -m <modulename>):

  • sys.path is modified to include the current directory
  • __name__ is set to '__main__'
  • __package__ is set to the immediate parent package in <modulename>
  • __init__.py is evaluated for all packages (including its own for package modules)
  • __main__.py is 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.

2 of 7
197

The first line of the Rationale section of PEP 338 says:

Python 2.4 adds the command line switch -m to allow modules to be located using the Python module namespace for execution as scripts. The motivating examples were standard library modules such as pdb and profile, 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 -m is 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.

🌐
GeeksforGeeks
geeksforgeeks.org › python › what-is-the-use-of-python-m-flag
What is the use of Python -m flag? - GeeksforGeeks
July 23, 2025 - For instance, you can run the timeit module to measure the execution time of a code snippet: ... This will display the time taken to execute the specified code snippet. ... In conclusion, the Python -m switch is a powerful tool that allows you ...
🌐
Python
docs.python.org › 3 › using › cmdline.html
1. Command line and environment — Python 3.14.4 documentation
An example is the timeit module: python -m timeit -s "setup here" "benchmarked code here" python -m timeit -h # for details · Raises an auditing event cpython.run_module with argument module-name.
🌐
Medium
foongminwong.medium.com › python-m-flag-5fc87ed31dba
python -m flag. I was testing one of the Python scripts… | by Foong Min Wong | Medium
March 28, 2024 - Then I ran python -m graphutils.plot to test the .py script in that folder, and it works!
Find elsewhere
🌐
Python Morsels
pythonmorsels.com › cli-tools
Python's many command-line utilities - Python Morsels
June 3, 2024 - Running Python with the -m command-line argument tells Python to run a given Python module as if it were a Python script. Some modules do something at import time. For example the antigravity module will open up a web browser for an XKCD comic.
🌐
Medium
swesadiqul.medium.com › why-is-used-m-in-command-5a642d5c1730
Why is used -m in command?. The -m option in the python command is… | by Sadiqul Islam | Medium
February 27, 2023 - When you use -m, Python looks for the module in the Python path, which includes the standard library and any other directories that you've added to the path. This means that you can run modules from anywhere on your system, as long as they're installed and in the Python path. It can be more convenient for one-time commands.
🌐
Quora
quora.com › What-does-m-mean-in-the-terminal-command-Python-m-pip-install-openpyxl
What does '-m' mean in the terminal command 'Python -m pip install openpyxl'? - Quora
Equivalent to invoking the pip module directly: python -m pip ... is more reliable than pip ... or pip3 ... which might call a different Python. Works for other modules too (for example python -m http.server starts a simple HTTP server).
🌐
Blogger
pythonwise.blogspot.com › 2015 › 01 › python-m.html
PythonWise: python -m
If it won't be simple, it simply won't be. [Hire me, source code] by Miki Tebeka, CEO, 353Solutions · python -m lets you run modules as scripts. If your module is just one .py file it'll be executed (which usually means code under if __name__ == '__main__').
🌐
Real Python
realpython.com › run-python-scripts
How to Run Your Python Scripts and Code – Real Python
February 25, 2026 - For example, if you want to run a Python module, then you can use the command python -m <module-name>. The -m option searches Python’s module search path, sys.path, for the module name and runs its content:
🌐
Reddit
reddit.com › r/learnpython › what is the -m flag's purpose?
r/learnpython on Reddit: What is the -m flag's purpose?
July 25, 2022 - Installed modules can have that main guard too, but how would you call those scripts/modules from the command line? You’d need to know the path to where they are which is usually some convoluted location on your computer. Instead you can use python -m some.module.
🌐
Luketudge
luketudge.github.io › introduction-to-programming › command_line.html
The command line — Introduction to Programming with Python
Just as Python functions may accept certain optional arguments that vary their behavior, so too do many programs that are run from the command line. In the context of the command line, these are sometimes called ‘options’ or ‘flags’. In command line syntax, options are preceded by a double dash -- (or sometimes a single dash - for abbreviated, single letter options), and follow the main command, separated by a space. For example, if we want to ask our Python interpreter program what version of Python it is, we can run it with the --version option.
🌐
Daily Dose of DS
blog.dailydoseofds.com › p › python-m-the-coolest-python-flag
What is the use of Python -m flag? - by Avi Chawla
December 25, 2023 - As depicted above, we can also use the -m flag instead of python utils.py. But as “executing the script” and the “-m flag” produce the same output, why and when would we prefer the ‘-m flag’ route? In my experience, there are two profound usages of the -m command line flag.
🌐
Reddit
reddit.com › r/python › what does -m flag do when running a python scripts.
r/Python on Reddit: What does -m flag do when running a python scripts.
May 18, 2022 -

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?

🌐
CodeRivers
coderivers.org › blog › python-m-command
Unveiling the Power of Python's `-m` Command - CodeRivers
April 2, 2025 - For example, the http.server module can be used to start a simple HTTP server. You can run it using: ... This will start a server on port 8000, serving the files in the current directory. Many third-party packages can be run using the -m command. For instance, the flake8 code linting tool can be executed as follows: ... This will run flake8 on the my_project directory, checking for code style violations. The pdb (Python Debugger) module can be used for debugging Python code.
🌐
iO Flood
ioflood.com › blog › python-terminal-commands
Python Terminal Commands: Reference Guide
November 21, 2023 - You can enter Python commands one at a time and see the results immediately. Here’s how you enter Python’s interactive mode: ... This command opens the Python interpreter in your terminal. You can now enter Python commands directly into the terminal. For example:
🌐
Refactoring.Guru
refactoring.guru › home › design patterns › command › python
Command in Python / Design Patterns
January 1, 2026 - Command pattern in Python. Full code example in Python with detailed comments and explanation. Command is behavioral design pattern that converts requests or simple operations into objects.
🌐
Reddit
reddit.com › r/learnpython › python -m flag
r/learnpython on Reddit: python -m flag
July 25, 2022 -

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.