Search code examples
pythonpip

How to configure pip to install a script to the environment bin/ folder?


I'm writing a package in Python, and I want possible users to install a command to their system by installing with pip. A package that I want to copy the installation behavior of is gdown. When you install this, a gdown python executable is put inside the environment's (whether it's global or a virtual environment) bin/ folder, so that gdown can be called from the command line.

How do I replicate this behavior? I tried to look at the code in the repository but I can't seem to find the code that does this.


Solution

  • Assume we're working with pyproject.toml, which is the standard by now.
    Let's distinguish between two use-cases:

    1. Making a Python script available as executable

    You can use [project.scripts] (official reference) to have an executable shortcut created to some python function (which is what gdown does too):

    [project.scripts]
    spam-cli = "spam:main_cli"
    

    This will create an executable spam-cli.exe (on Windows, inside Scripts/) or spam-cli (on Linux, inside bin/) that runs main_cli() from the installed spam.py file.

    The Poetry backend has it's own syntax to it:

    [tool.poetry.scripts]
    my_package_cli = "my_package.console:run"
    

    2. Installing an existing script or executable

    Instead you might want to make a shell script or compiled binary available with your pip package. As far as I know, the pyproject.toml standard doesn't support this. But, there are options for both the setuptools and Poetry backends:

    [tool.setuptools]
    script-files = [ "myscript" ]
    

    (See https://stackoverflow.com/a/74955996/4784914. Note: script-files is being discouraged though!)

    [tool.poetry.scripts]
    myscript = { reference = "some_binary.exe", type = "file" }
    

    I cannot find any documentation to back this up, oddly enough, but it works.

    This will copy the executable or script into the bin/ or Scripts/ directory, making them available directly from the CLI after installing the package.