Creating a setup process for a Python command line utility

Hi all,
I’ve recently created a Python script that I think can be useful to a lot of organizations. It presently exists as a standalone script which accepts various command line parameters that define the work it will do (e.g. python3 MyUtility.py --param1 something --param2 something).

It’ll be on GitHub shortly. I’d like to have a setup process for it where organizations can use something like PyPI to install it, but I’m not 100% sure PyPI meets all my requirements, which are:

  1. Install python libraries that are dependencies (that part I know PyPI can do)
  2. Install applications that are dependencies (e.g. MariaDB)
  3. After the installation is complete, have it in the path where it can be run at the command line with no extension (so a user can simply type MyUtility --param1 something --param2 something). This could be accomplished by copying it within /bin somewhere or just adding its install location to the path; the Python shebang is already in the script so it works without an extension.

It’s basically used as a command line utility and I can’t imagine a scenario where a script would need to import it. All the packaging examples I’ve encountered so far seem to be geared toward modules you’d be importing rather than something that’s a command-line utility, but maybe I’m not finding good examples.

Does anyone have a suggestion on the best way for me to package something like this for installation?

Thanks in advance.

Step 2 is not something that Python packaging does. The proper way to address non-Python dependencies is to document them in your README, and, if possible, have your script fail with helpful errors if the dependencies aren’t met at runtime.

As for installing a script in $PATH, this is done through the console_scripts entry point. Assuming your package is just the script MyUtility.py and it contains a main() function, and assuming you’re using setuptools, you would write the following in your setup.cfg:

[options.entry_points]
console_scripts =
    MyUtility = MyUtility:main
2 Likes

And if you really want to be able to streamline step 2 for users (note that not every user would want that, which is part of the reason why Python packaging doesn’t cover it), your script is no longer a Python package, but “an application that happens to be implemented in Python” (there are subtle differences, and a program can be both if it wants to). This means you’d distribute your program with non-Python-packaging means, e.g. deb, rpm, Homebrew, and more. Those package managers (usually called system package managers) can do more on a target platform and let you declare dependency on e.g. MariaDB.

1 Like

@DouglasQuaid Where did you land with this? Can you provide a link to the repo?

I’ve been working through a similar exercise, turning a personal Python script into an installable command-line utility, attempting to follow best-practices, while not going overboard. The result is up at GitHub - bhrutledge/zkeys: Display Zsh key bindings in more human-readable formats.

You can see that the initial commit is just the script; the first release adds a minimal packaging layout to enable pip install (or pipx install) and publishing to PyPI. From there, I added all of the dev tools that I like to use, plus some documentation for my own reference.

From here, I’m hoping to extract a cookiecutter, so that the next time I want to write such a tool, I can start with everything already set up.

Related: Add a tutorial/guide for creating a command line tool · Issue #615 · pypa/packaging.python.org · GitHub