I think you may be confusing two things. Having a src directory in your source distribution is a reasonably common, idiomatic thing to do; having that in the installed package or app, not so much.

There are two basic ways to structure this.


First, you can build a Python distribution that installs a package into site-packages, and installs a script into wherever Python scripts go on the PATH. The Python Packaging User Guide covers this in its tutorial on building and distributing packages. See the Layout and Scripts sections, and the samples linked from there.

This will usually give you an installed layout something like this:

<...somewhere system/user/venv .../lib/pythonX.Y/site-packages>
    app_name/
        file1.py
        file2.py
        cli.py
        __init__.py

<...somewhere.../bin/>
    app_name

But, depending on how the user has chosen to install things, it could instead be an egg, or a zipped package, or a wheel, or anything else. You don't care, as long as your code works. In particular, your code can assume that app_name is an importable package.

Ideally, the app_name script on your path is an "entry-point" script (pip itself may be a good example on your system), ideally one built on the fly at install time. With setuptools, You can just specify which package it should import and which function it should call in that package, it will do everything else—making sure to shebang the Python actually used at install time, figuring out how to pkg_resources up the package and add it to the sys.path (not needed by default, but if you don't want it to be importable, you can make that work), and so on.

As mentioned in a comment from the original asker, python-commandline-bootstrap might help you put this solution together more quickly.


The alternative is to keep everything out of site-packages, and make the package specific to your app. In this case, what you basically want to do is:

  • Install a directory that contains both the package (either as a directory, or zipped up) and the wrapper script.
  • In the wrapper script, add dirname(abspath(argv[0])) to sys.path before the import.
  • Symlink the wrapper script into some place on the user's PATH.

In this case, you have to write the wrapper script manually, but then you don't need anything fancy this way.

But often, you don't really want an application to depend on the user having some specific version and setup of Python. You may want to use a tool like pyInstaller, py2exe, py2app, cx_Freeze, zc.buildout, etc. that does all of the above and more. They all do different things, all the way up to the extreme of building a Mac .app bundle directory with a custom, standalone, stripped Python framework and stdlib and a wrapper executable that embeds the framework.


Either way, you really don't want to call the package directory src. That means the package itself will be named src, which is not a great name. If your app is called spamifier, you want to see spamifier in your tracebacks, not src, right?

Answer from abarnert on Stack Overflow
Top answer
1 of 1
8

I think you may be confusing two things. Having a src directory in your source distribution is a reasonably common, idiomatic thing to do; having that in the installed package or app, not so much.

There are two basic ways to structure this.


First, you can build a Python distribution that installs a package into site-packages, and installs a script into wherever Python scripts go on the PATH. The Python Packaging User Guide covers this in its tutorial on building and distributing packages. See the Layout and Scripts sections, and the samples linked from there.

This will usually give you an installed layout something like this:

<...somewhere system/user/venv .../lib/pythonX.Y/site-packages>
    app_name/
        file1.py
        file2.py
        cli.py
        __init__.py

<...somewhere.../bin/>
    app_name

But, depending on how the user has chosen to install things, it could instead be an egg, or a zipped package, or a wheel, or anything else. You don't care, as long as your code works. In particular, your code can assume that app_name is an importable package.

Ideally, the app_name script on your path is an "entry-point" script (pip itself may be a good example on your system), ideally one built on the fly at install time. With setuptools, You can just specify which package it should import and which function it should call in that package, it will do everything else—making sure to shebang the Python actually used at install time, figuring out how to pkg_resources up the package and add it to the sys.path (not needed by default, but if you don't want it to be importable, you can make that work), and so on.

As mentioned in a comment from the original asker, python-commandline-bootstrap might help you put this solution together more quickly.


The alternative is to keep everything out of site-packages, and make the package specific to your app. In this case, what you basically want to do is:

  • Install a directory that contains both the package (either as a directory, or zipped up) and the wrapper script.
  • In the wrapper script, add dirname(abspath(argv[0])) to sys.path before the import.
  • Symlink the wrapper script into some place on the user's PATH.

In this case, you have to write the wrapper script manually, but then you don't need anything fancy this way.

But often, you don't really want an application to depend on the user having some specific version and setup of Python. You may want to use a tool like pyInstaller, py2exe, py2app, cx_Freeze, zc.buildout, etc. that does all of the above and more. They all do different things, all the way up to the extreme of building a Mac .app bundle directory with a custom, standalone, stripped Python framework and stdlib and a wrapper executable that embeds the framework.


Either way, you really don't want to call the package directory src. That means the package itself will be named src, which is not a great name. If your app is called spamifier, you want to see spamifier in your tracebacks, not src, right?

🌐
Python Packaging
packaging.python.org › en › latest › guides › creating-command-line-tools
Creating and packaging command-line tools - Python Packaging User Guide
The file __main__.py marks the main entry point for the application when running it via runpy (i.e. python -m greetings, which works immediately with flat layout, but requires installation of the package with src layout), so initialize the command-line interface here:
Discussions

Directory structure of a command line app
That could work fine. I usually have a top line directory called "data", and then within that put subdirectories named for their usage: "temp", "exe". But what you're doing isn't really just data that's being manipulated, but other programs. So I'd say if it works for you, what you've suggested looks pretty clean. More on reddit.com
🌐 r/learnpython
10
4
April 4, 2024
I wrote a guide to creating and distributing CLI tools in Python and thought it might be appreciated here!
I wrote this over 2 years ago and forgot to share it here. It went mostly ignored on r/Python . I go over how to do argument parsing, how to use PyPI for distribution, how to get pretty colours in the terminal, etc. Let me know if anything is unclear or you have any feedback! More on reddit.com
🌐 r/commandline
9
60
May 3, 2023
Command Line Application Frameworks?
Hi, I'm more of a "down to the metal" kind of person, but I do use a few convenience wrappers for my shell utilities. (I actually have started writing all my new "shell scripts" in Go). The stuff I like is: github.com/aybabtme/rgbterm Very simple colorizer lib for output. github.com/codeskyblue/go-sh Makes working with external commands a fair bit simpler. Basically just syntactic sugar around the standard lib though. github.com/nsf/termbox-go A pure Go implementation of Termbox, which is an ncurses alternative. What I really like about it is that it has no non-Go dependencies, and is extremely minimal. It gives you the framework for building "gui" apps in the CLI, but makes you do all of the actual work of drawing characters to the screen. And then of course, I use the standard library quite extensively. For example, I find the "flag" package to be more than sufficient for doing command line flags. More on reddit.com
🌐 r/golang
17
24
September 5, 2014
Best way to make a CLI menu tree
If you're going to have a number of different types of menu, with different options, that all need to be handled similarly, you probably want to make a menu class. The class can store a list of options and have a print method (maybe better yet just have a __repr__ method, so you can call print(menu)). The print function can handle attaching numbers and formatting. A list is probably more on point than an ordered dict here since you'll generally be looking entries up by index anyway. The entries in the list can either just be labels, or could be tuples of some sort where the extra entries don't get printed, but contain any information your program needs. More on reddit.com
🌐 r/learnpython
6
2
March 19, 2015
🌐
The Hitchhiker's Guide to Python
docs.python-guide.org › scenarios › cli
Command-line Applications — The Hitchhiker's Guide to Python
Cliff is a framework for building command-line programs. It uses setuptools entry points to provide subcommands, output formatters, and other extensions. The framework is meant to be used to create multi-level commands such as svn and git, where the main program handles some basic argument parsing and then invokes a sub-command to do the work. Cement is an advanced CLI Application Framework.
🌐
Real Python
realpython.com › python-application-layouts
Python Application Layouts: A Reference – Real Python
April 23, 2026 - You’ll see examples of common Python application structures, including command-line applications (CLI apps), one-off scripts, installable packages, and web application layouts with popular frameworks like Flask and Django.
🌐
Thomas Stringer
trstringer.com › easy-and-nice-python-cli
The easy (and nice) way to do CLI apps in Python | Thomas Stringer
October 20, 2016 - There are a few ways to do the command-line app thing in Python. I’ve done these few ways, and some of them have their pain-points and annoyances. So I reached out to the community to find what the better way is (I hate to say “best”, as possibly there is something that is better than this). “CLI” stands for “command line interface”. It’s a type of application that is invoked through the command-line/terminal/shell/whatever.
🌐
Reddit
reddit.com › r/learnpython › directory structure of a command line app
r/learnpython on Reddit: Directory structure of a command line app
April 4, 2024 -

Hello,

I'm writing a Python 3 command line app with argparse, following the Real Python guide. They suggest the following directory structure in their toy app:

hello_cli/
│
├── hello_cli/
│   ├── __init__.py
│   ├── __main__.py
│   ├── cli.py
│   └── model.py
│
├── tests/
│   ├── __init__.py
│   ├── test_cli.py
│   └── test_model.py
│
├── pyproject.toml
├── README.md
└── requirements.txt

At one point in the process flow, my app will use subprocess to call two external executable files. One exe will generate a collection of run-specific files (representing a database). The other exe will compare a query against this database file set to generate a final results_file that will be further processed by the app. All of these files will be overwritten whenever the app is run.

Can someone tell me where these exes and temp files should be stored? I was thinking two more directories at the same level as tests and then store the exes in one and the run-specific files in the other (but I'm not sure if there's a standard way to store these). So, keeping with the original example template, something like:

Before run:

hello_cli/
│
├── hello_cli/
│   ├── __init__.py
│   ├── __main__.py
│   ├── cli.py
│   └── model.py
│
├── tests/
│   ├── __init__.py
│   ├── test_cli.py
│   └── test_model.py
│
├── executables/
│   ├── exe_1
│   └── exe_2
│
├── temp_files/
│
├── pyproject.toml
├── README.md
└── requirements.txt

Which, after run, will become:

hello_cli/
│
├── hello_cli/
│   ├── __init__.py
│   ├── __main__.py
│   ├── cli.py
│   └── model.py
│
├── tests/
│   ├── __init__.py
│   ├── test_cli.py
│   └── test_model.py
│
├── executables/
│   ├── exe_1
│   └── exe_2
│
├── temp_files/
│   ├── db_file_1
│   ├── db_file_2
│   │   ...     
│   ├── db_file_N
│   └── results_file
│
├── pyproject.toml
├── README.md
└── requirements.txt

What do you think?

Cheers!

🌐
Medium
medium.com › @ernestwinata › best-practices-for-structuring-a-python-cli-application-1bc8f8a57369
Best Practices for Structuring a Python CLI Application | by Ernest Winata | Medium
August 25, 2023 - In this project, I used a structured approach by dividing the code into distinct modules that handle different aspects of the application: Models Module (models.py): to manage the database and to define data schema, I have created this module to define SQLAlchemy models for ‘Country’ and ‘Landmark’. CLI Commands Module (cli.py): for handling user interactions and CLI commands, I have created a module named cli.py.
Find elsewhere
🌐
GitConnected
levelup.gitconnected.com › python-command-line-project-architecture-design-2c0adfed4da8
Python Command-Line Project — Architecture Design | by James K. Ralph | Level Up Coding
April 30, 2020 - In the above structure, we added resources directory which is only going to hold non-python files that may get used in some code present in its parent directory only. We don’t want to add an __init__.py here as this place would not have any python code. However, we need to tell our build tool to include these directories.
🌐
Honeybadger
honeybadger.io › blog › building-command-line-applications-in-python-a-comprehensive-guide
Building command-line applications in Python - Honeybadger Developer Blog
March 19, 2024 - Hence, flags are used in a command line application to turn specific features on or off. Usually, we execute a Python program from the command-line terminal using the syntax python filename.py or python3 filename.py.
🌐
Coderwall
coderwall.com › p › lt2kew › python-creating-your-project-structure
Python: Creating Your Project Structure (Example)
August 26, 2025 - Python has excellent libraries for parsing command-line arguments and running other shell commands, while at the same time you can take advantage of the powerful object-oriented language. Additionally you can verify and document your application with the Python's unit testing framework. The Example Application for this text can be found in github.com/mrako/python-example-project. ... In my experience the best folder structure for a Python project is to put your executables in a bin folder and your project into a your project name folder (I will use name project in this text).
🌐
Medium
medium.com › @trstringer › the-easy-and-nice-way-to-do-cli-apps-in-python-5d9964dc950d
The easy (and nice) way to do CLI apps in Python | by Thomas Stringer | Medium
June 9, 2020 - The easy (and nice) way to do CLI apps in Python. This blog post has been permanently moved to https://trstringer.com/easy-and-nice-python-cli/.
🌐
Datasciencehorizons
datasciencehorizons.com › building-python-cli-applications-step-by-step-tutorial
Building Python CLI Applications: A Step-by-Step Tutorial – Data Science Horizons
The sys module in Python allows basic command-line input handling, enabling you to access arguments passed to the script. import sys def main(): print("Arguments passed:", sys.argv) if __name__ == "__main__": main() Organizing your project directory is key to maintaining a clean and manageable ...
🌐
Real Python
realpython.com › python-typer-cli
Build a Command-Line To-Do App With Python and Typer – Real Python
July 3, 2026 - Then you need to give the project a coherent Python application layout. That’s what you’ll do in the following subsections. To download all the files and the project structure you’ll be creating in this section, click the link below and go to the source_code_step_1/ directory: Get Source Code: Click here to get the source code you’ll use to build a to-do app for your command line using Python and Typer.
🌐
GitHub
github.com › AnthonyBloomer › python-cli-template
GitHub - AnthonyBloomer/python-cli-template: A starting point for building Python Command Line Applications. · GitHub
This project serves as a starting point to developing command line modules with Python. It is structured in such a way that when we call the module it executes the main method in app/cli.py.
Author: AnthonyBloomer
🌐
Gehrcke
gehrcke.de › 2014 › 02 › distributing-a-python-command-line-application
Distributing a Python command line application – Jan-Philip Gehrcke, PhD
February 11, 2023 - I have created a git repository from this structure template: python-cmdline-bootstrap on GitHub. Fell free to clone and fork. Might look random in parts, but it is not. Clarification: All relevant application code is stored within the bootstrap package (which is the bootstrap/ directory containing the __init__.py file). bootstrap-runner.py is just a simple wrapper script that allows for direct execution of the command line application from the source directory, without the need to ‘install’ the application.
🌐
Pybites
pybit.es › articles › how-to-package-and-deploy-cli-apps
How to package and deploy CLI applications with Python PyPA setuptools build – Pybites
August 30, 2021 - The pip install command will install your package and create the CLI shortcuts (the ones you specified in setup.cfg) in the current Python environment’s bin directory. ... Under the hood, these shortcut files are actually just a more sophisticated version of the quick-and-dirty bash file we created in the beginning. The auto-generated my-application shortcut file in the bin/ directory looks like this:
🌐
Real Python
realpython.com › python-click
Click and Python: Build Extensible and Composable CLI Apps – Real Python
March 18, 2026 - Nested commands, or subcommands, are one of the most powerful and distinctive features of Click. What’s a subcommand anyway? Many command-line applications, such as pip, pyenv, Poetry, and git, make extensive use of subcommands. For example, pip has the install subcommand that allows you to install Python packages and libraries in a given environment.
🌐
Medium
denyslinkov.medium.com › scaling-your-python-cli-87f74a0fb6cb
Scaling Your Python CLI. How to maker your programs modular | by Denys Linkov | Medium
October 13, 2021 - Now we have a choice on how we’d like our users to interact with our cli, either structuring it so that commands go verb first or noun first, i.e cli create file or cli file create. In the next section we’ll discuss some pros and cons of each approach. Depending on which CLIs you have worked with, the natural hierarchy for your cli might be cli create file or cli file create . The first one is called a verb-noun hierarchy with clis like Powershell. These structures are great when commands have similar actions that can be taken and mirrors english more closely.
🌐
Simon Willison
simonwillison.net › 2023 › Sep › 30 › cli-tools-python
Things I’ve learned about building CLI tools in Python
September 30, 2023 - Arguments are positional—they are strings that you pass directly to the command, like data.db in datasette data.db. Arguments can be required or optional, and you can have commands which accept an unlimited number of arguments.
🌐
Vanilla-project
vanilla-project.guide › python › command-line
Python Command Line Application - Vanilla Project
You want to learn a new language? Great · Our aim is to provide guides in various languages and different tooling to help you get started with a new environment