What is `-m` stands for in `python -m unittest`? - python

What is -m stands for in python -m unittest? The unittest unit testing framework has other command line options like -v -b -c -t but wondering what does -m stands for? Is it part of unittest or other python command line option?

if you run python --help you will see that:
-m mod : run library module as a script (terminates option list)
An explanation as to what that means and -m flage does can be found here, I have copied the important parts below:
Properly designed modules usually do nothing except set up stuff (e.g. functions and types you could import), but they usually won’t have any visible side effect. That’s why you can do import sys and nothing happens.
However, some modules may offer useful stuff when they are run from the command line. Examples for that include venv but also http.server or idlelib: All of those are regular modules that can be imported from other modules without side effects.
But when executed directly, they all do things (e.g. venv sets up a virtual environment, http.server runs a simple HTTP server, and idlelib runs IDLE). This is usually done with the following check:

Related

How to run a module from the command line with options?

Modules in python can be run from the pipeline with the -m option:
python -m pytest
This runs pytest with the advantage that the current directory is added to sys.path.
Now I want to run pytest with the -verbose option, but surrounding it with quotes/ticks does not work:
python -m pytest -verbose
python -m "pytest -verbose"
python -m 'pytest -verbose'
python -m `pytest -verbose`
How do I use options when running pytest with python from the CLI?
EDIT: The comment from Dinari solved it, I mistakenly used -verbose instead of --verbose
You should use:
python -m pytest --verbose instead
Notice the double dash instead of the single dash.
You use the single dash when using the short version usually -v ,however, here you use —verbose as you are using the long version.

Profiling module in PyCharm

Following up on this question:
Create a PyCharm configuration that runs a module a la "python -m foo"
Running and debugging modules works great for me with the new option from 2018.1, for which you can now specify a module to run. However, profiling the same configuration does not work.
PyCharm tries to run something like this:
/path/to/python /path/to/pycharm/plugins/python/helpers/profiler/run_profiler.py 127.0.0.1 44725 -m mypackage.cli.runthis paramA paramB
For whatever reason, all parameters (especially the -m) are forwarded to my package, and argparse complains that it doesn't know -m. As I said before, this configuration works perfectly fine for running/debugging. Any idea how I could get the profiler working?

What does the -m option stand for in python?

When creating a virtual environment, I run:
python3 -m venv env
I understand that -m executes a module (venv in this case). However, what does the -m flag actually stand for?
Is it -m for module, or -m for __main__?
I couldn't find an unambiguous explanation. Here are some resources I investigated:
https://docs.python.org/2/using/cmdline.html#cmdoption-m
https://www.python.org/dev/peps/pep-0547/
Execution of Python code with -m option or not
in
section 1.1.1
It clearly says -m is the module name, here.
Quoting from the docs :
"since the argument is a module name, you must not give a file extension (.py). The module-name should be a valid Python module name"
Although -m is arbitrary as in the backend It is an argparser doing all the work.
When called with -m module-name, the given module is located on the Python module path and executed as a script
Package names are also permitted. When a package name is supplied instead of a normal module, the interpreter will execute <pkg>.__main__ And I guess the main also starting with 'm' is a coincidence.
It runs the module following -m. See the official documentation
The documentation says -m <module-name>, as well as "Since the argument is a module name...", so it makes sense to assume that "m" stands for module.

Execute an installed Python package as a script?

Is there a way to enable a package to be executed as a script? For example:
[~]# easy_install /path/to/foo.egg
...
[~]# python -m foo --name World
Hello World
I've tried creating a __main__.py file inside my package but it's not being executed (I'm using Python 2.6). The following error is raised:
foo is a package and cannot be directly executed
The structure of my package is as follows:
foo/
setup.py
foo/
__init__.py
__main__.py
Running python -m foo.__main__ --name World works as expected, but I would prefer the former way of execution. Is this possible?
This is a regression in Python 2.6. See issue2571:
The ability to execute packages was never intended, since doing so
breaks imports in a variety of subtle ways. It was actually a bug in
2.5 that it was permitted at all, so 2.6 not only disabled it again, but also added a test to make sure it stays disabled (2.4 correctly
rejected it with an ImportError, just as 2.6 does).
You have a few options, you can either always run it specifying main:
$ python -m module.__main__
Or you can write a shell script wrapper that detects the python version and then executes it in the different style.
Or you can execute code on the command line that will import and then run the module, and then perhaps place that in a shell script:
$ python -c "import module; module.main()"
In my own command-line projects I have both the shell script that catches errors (python not being installed, etc.) but the shell script will also execute the import code and detect if the necessary modules have been installed and prompt an error (with a helpful link or install text).
I think this may be a limitation of Python 2.6. I've tested it, and executing a package (either in . or installed from an egg with easy_install) with the -m option works fine in 2.7, but not in 2.6. For example, on my system (Ubuntu) with a test package called pkg_exec in the current directory, and where __main__.py simply prints sys.argv:
xx#xx:~/tmp/pkg_exec$ python2.6 -m pkg_exec
/usr/bin/python2.6: pkg_exec is a package and cannot be directly executed
xx#xx:~/tmp/pkg_exec$ python2.7 -m pkg_exec
['/home/xx/tmp/pkg_exec/pkg_exec/__main__.py']
Also, according to the 2.7 docs:
Changed in version 2.7: Supply the package name to run a __main__ submodule.
Yes, you can do that if the script has the __main__ section.
Of course, you can't execute a package if it is a directory. But if you can run the script itself (say it starts with #!/usr/bin/python3 and you run it with ./script), you can choose another interpreter this way:
/bin/python2 -v ../path/to/my/script status
where -v is for the interpreter (if needed), and status is an argument for your script.
as long as the package is on the python path,
add at the end of the script.
if __name__ == "__main__":
call_script()
$ python -m module_name
will run the module e.g
python -m random

Getting pdb in Emacs to use Python process from current virtualenv

I am debugging some python code in emacs using pdb and getting some import issues. The dependencies are installed in one of my bespoked virtualenv environments.
Pdb is stubbornly using /usr/bin/python and not the python process from my virtualenv.
I use virtualenv.el to support switching of environments within emacs and via the postactivate hooks described in
http://jesselegg.com/archives/2010/03/14/emacs-python-programmers-2-virtualenv-ipython-daemon-mode/
This works well when running M-x python-shell
>>> import sys
>>> print sys.path
This points to all of my virtualenv libraries indicating that the python-shell is that of my virtualenv.
This is contradicted however by M-! which python, which gives /usr/bin/python
Does anyone know how I can tell M-x pdb to adopt the python process from the currently active virtualenv?
Invoke pdb like this:
python -m pdb myscript.py
Instead of
pdb myscript.py
python-shell uses variable python-default-interpreter to determine which python interpreter to use. When the value of this variable is cpython, the variables python-python-command and python-python-command-args are consulted to determine the interpreter
and arguments to use. Those two variables are manipulated by virtualenv.el to set the current virtual environment.
So when you use python-shell command, it uses your virtual environments without any problem.
But, when you do M-! python, you're not using the variables python-python-command and python-python-command-args. So it uses the python tools it finds in your path.
When you call M-x pdb it uses gud-pdb-command-name as the default pdb tool. To redefine this variable, each time you activate an environment, you could do something like this :
(defadvice virtualenv-activate (after virtual-pdb)
(custom-set-variables
'(gud-pdb-command-name
(concat virtualenv-active "/bin/pdb" ))))
(ad-activate 'virtualenv-activate)
To have pdb in your virtual environment, do the following :
cp /usr/bin/pdb /path/to/virtual/env/bin
Then edit the first line of /path/to/virtual/env/bin/pdb to have :
#! /usr/bin/env python
Reactivate your env and Pdb should now use your virtualenv python instead of the system-wide python.
Possibly, your pdb command is tied to a certain specific version.
$ ls -ald /usr/bin/pdb
lrwxrwxrwx 1 root root 6 Jun 2 23:02 /usr/bin/pdb -> pdb2.6
Then, look at the first line of pdb2.6. It contains
#! /usr/bin/python2.6
This is why pdb is stubborn and always seems to run under a specific version of Python. Because it really is! Actually, this sort of dependency makes sense for a piece of software like a symbolic debugger.
I've compiled python2.7 from sources and pdb is not there, apparently.
After some scrutiny, I found pdb.py for python-2.7, under the lib folder.
I've then created some symlinks to it, for convenience:
$ cd /opt/python-dev ##-- this is where I installed from sources
$ cd bin
$ sudo ln -s ../lib/python2.7/pdb.py pdb2.7
$ sudo ln -s pdb2.7 pdb
Now observe the first line of pdb2.7. It reads:
#! /usr/bin/env python
... which looks better than the previous version. It basically means that pdb will be launched under the current Python you have defined in your environment, whatever it is, instead of anything hardcoded, like /usr/bin/python or /usr/bin/python2.6 are. Good to know!
I've also removed pdb and pdb2.6 from system files, once I prefer to develop/debug inside virtualenv. Doing that, I will not be caught again by the same trick.
I hope it helps.
A quick work-around is to explicitly call the python interpreter in you virtual env.
M-x pdb, then:
path/to/your/virtualenv/python3 -m pdb your_source.py

Categories