pythoncommand-line-interfacesetuptoolspython-packagingpyproject.toml

Python packaging with pyproject.toml and setuptools


What I am trying to achieve

My goal is, after installing the python package, to be able to run a command without having to type python before the command.

Example

$ excommand
Hello, World!

Directory Structure

.
├── example
    ├── __init__.py
    └── exmodule.py
├── .venv
├── pyproject.toml
└── setup.cfg

exmodule.py

def command():
    print("Hello, World!")

pyproject.toml

[build-system]
requires = [ "setuptools" ]
build-backend = "setuptools.build_meta"

setup.cfg

[metadata]
name = Example
version = 1.0.0

[options]
packages = find:

[options.entry_points]
console_scripts = 
    excommand = example.exmodule:command

The Problem

After the execution of the following command on terminal:

$ python3 -m build --wheel

No warnings or errors are printed to the terminal but the command does not work:

$ excommand
zsh: command not found: excommand

What was tried

Before using the TOML file, I was just using the setup.cfg file with a setup.py, but when installing the package with the command pip install . I was warned that future versions of pip would guarantee the use of TOML files. It was not working either, so tried using TOML.


Solution

  • With newer setuptools and pyproject.toml you can use: (only relevant parts included)

    [build-system]
    build-backend = 'setuptools.build_meta'
    requires = ["setuptools>=69.2.0", "setuptools-scm"]
    
    [tool.setuptools]
    packages = ["yourpackage"]
    
    [project.scripts]
    yourbinary = "yourpackage.yourpackage:main"
    

    You must create a main() function in your yourpackage.yourpackage.py:

    #<all your fantastic code>
    
    def main():
        parser = argparse.ArgumentParser(description='superdupermain')
        parser.add_argument('--debug', help='debug', action='store_true')
        :
    
    if __name__ == '__main__':
       main()
    

    When you run pip install yourpackage in a <venv> it will install:

        <venv>\lib\site-packages\yourpackage\yourpackage.py
        <venv>\scripts\yourbinary.exe
    

    It will be in your path so you can execute yourbinary.exe for linux it will be an executable yourbinary