question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

detection of program name when run with `python -m`

See original GitHub issue

The program name (referred to as prog_name or info_name) is the name Click uses in usage help text. If it’s not specified, Click tries to detect it by looking at sys.argv[0].

https://github.com/pallets/click/blob/dfb842d95a7c146d8fe8140c8100065410d95c4d/src/click/core.py#L797-L800

This works when the CLI is run as a script, either directly, or indirectly as an entry point, or as a module when the program is a single file, but fails when the program is a package and run with python -m. In that case, Python converts the -m name to the Python file within the package that would be executed. (The use of __file__ there is also incorrect, as that will always point to click/core.py. There should never be a case where sys.argv is empty. make_str is probably not needed either.)

This leads to the following names:

  • python example.py, executing a script directly - example.py
  • python -m example, the single file module example.py - example.py
  • python -m example, a package like example/__main__.py - __main__.py
  • python -m example.cli, a submodule like example/cli.py - cli.py
  • example, an entry point, with any of the layouts above - example

What’s usually expected is that executing a script will print the Python file name (example.py), executing an entry point will print the entry point name (example), and executing a module or package will print the Python command (python -m example, python -m example.cli)

This leads to projects that expect to be run as either an entry point or -m writing their own wrapper around the CLI to control what name gets used. For example, Flask uses a wrapper that the entry point will call with no args, while __main__.py or __name__ == "__main__" will pass as_module=True.

def main(as_module=False):
    cli.main(prog_name="python -m flask" if as_module else None)

Unfortunately, detecting whether python -m was used is really, really complicated. Luckily, I did the work already in Werkzeug’s reloader: https://github.com/pallets/werkzeug/blob/102bcda52176db448d383a9ef1ccf7e406a379eb/src/werkzeug/_reloader.py#L59. It won’t be quite the same in Click because we’re not concerned with the exact path to the python command or script file, or with arguments, but that should be a good start. Write a function detect_program_name() to detect this and call it in place of the existing code.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
davidismcommented, Jun 25, 2020

Here’s a simple project to test out the commands with. example.tar.gz

$ tar xf example.tar.gz
$ cd example
$ python3 -m venv venv
$ . venv/bin/activate
$ pip install -e ../click  # wherever your click repo is
$ pip install -e .

Now you can do different commands and changes you make to your click repo will be reflected. The command echos the detected program name.

$ python -m example
$ python -m example.cli
$ example
$ python single.py
$ python -m single
1reaction
gmelodiecommented, Jun 29, 2020

@ovezovs thanks! @kbanc set up a windows VM and got it done 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

Detecting program's name Python 3 [duplicate] - Stack Overflow
I am working on a project and one part of it is to have the program tell what it's own name is. I...
Read more >
__main__ — Top-level code environment — Python 3.11 ...
In Python, the special name__main__ is used for two important constructs: the name of the top-level environment of the program, which can be...
Read more >
Usage and Invocations — pytest documentation
You can invoke testing through the Python interpreter from the command line: python -m pytest [...] This is almost equivalent to invoking the...
Read more >
Python Tutorial - if __name__ == '__main__' - BogoToBogo
For example, if the python interpreter is running that module (the source file) as the main program, it sets the special __name__ variable...
Read more >
Python Command Line Arguments
Python exposes a mechanism to capture and extract your Python command line arguments. These values can be used to modify the behavior of...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found