pythonprogram-entry-pointsetuptoolsentry-point

Python Setuptools: quick way to add scripts without "main" function as "console_scripts" entry points


My request seems unorthodox, but I would like to quickly package an old repository, consisting mostly of python executable scripts.

The problem is that those scripts were not designed as modules, so some of them execute code directly at the module top-level, and some other have the if __name__=='__main__' part.

How would you distribute those scripts using setuptools, without too much rewrite?

Is there a way to create scripts from modules? At least when they have a if __name__=='__main__'?


Solution

  • There's some design considerations, but I would recommend using a __main__.py for this.

    1. it allows all command line invocations to share argument parsing logic
    2. you don't have to touch the scripts, at all
    3. it is explicit (no do-nothing functions that exist to trigger import)
    4. it enables refactoring out any other common stateful logic, since __main__.py is never imported when you import your package
    5. convention. People expect to find command line invocations in __main__.py.

    __main__.py

    from pathlib import Path
    from runpy import run_path
    
    pkg_dir = Path(__file__).resolve().parent
    
    def execute_script():
        script_pth = pkg_dir / "local path to script"
        run_path(str(script_pth), run_name="__main__")
    
    

    Then, you can set your_package.__main__:execute_script as a console script in setup.py/pyproject.toml. You can obviously have as many scripts as you like this way.