Building your first Python command-line app
Building your own Python app and deploying it to PyPi can seem daunting. It’s not! If you know Python and have a a little familiarity with the command line, you can get an app out the door in a day.
I recently built a small tool to solve for a simple use case: I want an easy way to create new AWS Budgets from the command line. I’ve left some AWS services running that 1.) were more expensive than I thought or 2.) that I’d forgotten to turn off. Budgets make sure this never happens.
I’ll be using code from my app below.
Since this my first time deploying an app on PyPi, there may be mistakes and misunderstanding lurking in the article. Please comment on those below if you find any.
I want to build a command-line app. How do I start?
I’ve used argparse in the past to build Python command line apps, but click seems to be popular in 2018. It facilitates the process of creating CLI apps (less code than argparse), and includes more bells and whistles (styling of output, etc.).
If you’ve ever used Flask, click’s API for tying command line options to code (using function decorators) should feel familiar:
This code can be run like so:
$ python hello.py --count=3
Your name: John
Out of the box, this script also supports the
--help option, which prints usage information.
I’ve written my app. Now I want to deploy it to PyPi.
This process was much easier than I expected. I do not want to duplicate the already amazing documentation for packaging and deploying your app to PyPi, so I’ll cover the high level and talk about some of the gotchas I encountered.
- Structure your code / files in the right format.
- Write a setup.py file to describe the package metadata (most of my time was spent here).
- Create accounts on PyPi’s test and production servers. You’ll use these accounts to upload your code to PyPi.
- Upload your code to PyPi’s test server. Once you’re 👍, deploy it to production.
I didn’t spend enough time reading through the documentation for the
setup.py file, so struggled to get a few things working there.
setup.py learnings and gotchas
I’ll be referring to my
setup.py file on GitHub below.
One README for all documentation
If you’re using a
README for your documentation elsewhere (e.g. GitHub), you can also use that as the documentation for your PyPi package!
Just read the contents of your
README as a string:
with open(“README.md”, “r”) as fh:
long_description = fh.read()
and within the
setup() function, set the
long_description to that string, making sure to also set the
long_description_content_type to the appropriate type (Markdown, RST, etc.):
Include sub-packages in the main package
I wanted to break out code into smaller sub-packages. For instance, I’ve written a
CloudFormationClient class to manage interaction with AWS CloudFormation, and I’ve broken that out into its own package:
$ ls CloudFormationClient
In order to package this code with your larger application, you’ve got to keep your code in a structure like this, with an
__init__.py file at its root.
Next, make sure to import the
from setuptools import setup, find_packages
Then, add the following line in your
More about the
find_packages function here.
Include data / config files within your package
I assumed every file in my package would be included in that package. That’s not the case.
For instance, that
budgets.template.yaml file in the
CloudFormationClient directory was critical to the tool, but it didn’t get packaged with the code initially.
I had to set this flag in my
From the docs:
If set to
True, this tells
setuptoolsto automatically include any data files it finds inside your package directories that are specified by your
So I had to enumerate everything I wanted to include in that
Packaging a click command-line app
Click includes some helpful docs on packaging your command-line app with
entry_points argument to the
setup() function must point to the function you want to run when the user runs your CLI app:
setuptools are clearly documented, so it should be easy for someone with a little Python knowledge to dive right in.
Take a look at some of the
setup.py files for your favorite Python package — they can get very complex!
Let me know if you’ve written your own Python package and learned anything worth sharing in the comments below.