4

In order to make pip or jupyter available from command-line on Windows no matter the current working directory with just pip ... or jupyter ..., Python on Windows seems to use this method:

  • put C:\Python37\Scripts in the PATH
  • create a small 100KB .exe file C:\Python37\Scripts\pip.exe or jupyter.exe that probably does not much more than calling a Python script with the interpreter (I guess?)

Then doing pip ... or jupyter ... in command-line works, no matter the current directory.

Question: how can I create a similar 100KB mycommand.exe that I could put in a directory which is in the PATH, so that I could do mycommand from anywhere in command-line?


Note: I'm not speaking about pyinstaller, cxfreeze, etc. (that I already know and have used before); I don't think these C:\Python37\Scripts\ exe files use this.

Basj
  • 41,386
  • 99
  • 383
  • 673

1 Answers1

3

Assuming you are using setuptools to package this application, you need to create a console_scripts entry point as documented here:

For a single top-level module it could look like the following:

setup.py

#!/usr/bin/env python3

import setuptools

setuptools.setup(
    py_modules=['my_top_level_module'],
    entry_points={
        'console_scripts': [
            'mycommand = my_top_level_module:my_main_function',
        ],
    },
    # ...
    name='MyProject',
    version='1.0.0',
)

my_top_level_module.py

#!/usr/bin/env python3

def my_main_function():
    print("Hi!")

if __name__ == '__main__':
    my_main_function()

And then install it with a command such as:

path/to/pythonX.Y -m pip install path/to/MyProject
sinoroc
  • 18,409
  • 2
  • 39
  • 70
  • For a top level module: `'mycommand = my_top_level_module:my_main_function'`. – sinoroc May 23 '20 at 10:49
  • 1
    These are too many questions. I would recommend you read the whole page linked in my answer, or first start with a shorter tutorial such as this one: https://packaging.python.org/tutorials/packaging-projects/ – sinoroc May 23 '20 at 10:58
  • Not sure if it the same issue you had, but there was a mistake in my example. The parameter `py_modules` takes a list as argument, so it should read: `py_modules=['my_top_level_module']`. Maybe this was the same issue on your side. – sinoroc May 23 '20 at 16:03
  • It solved the problem @sinoroc, thanks! PS: I edited to add the alternate `python setup.py install`. – Basj May 23 '20 at 18:05
  • Nowadays it is not recommended to use `python setup.py install` anymore. It often works the same but there are cases where it won't so using _pip_ is preferred. – sinoroc May 24 '20 at 08:38
  • Thanks for this info @sinoroc. Do you have a source/article about this deprecation of `python setup.py install`? I found this https://stackoverflow.com/questions/1550226/python-setup-py-uninstall/1550235#1550235 but maybe is there a PEP or more authoritative info about "don't use python setup.py"? I'll try to find this, and I'll post it here in case I find something. – Basj May 24 '20 at 09:12
  • 1
    No official statement yet, but if you have followed [PEP 517](https://www.python.org/dev/peps/pep-0517/) and [PEP 518](https://www.python.org/dev/peps/pep-0518/), then more or less: _setuptools_ is backend, _pip_ is frontend. So the build/install frontend (_pip_) calls the backend (could be _setuptools_ or anything else), and the user experience is consistent. Here are some statements: https://github.com/pypa/setuptools/issues/1983#issuecomment-584130062 -- https://github.com/pypa/setuptools/issues/529#issuecomment-432286537 – sinoroc May 24 '20 at 09:34