If the whole application fits into a single file, that is the most simple solution.
Otherwise, it is best to create a complete package. When you create a setuptools-based
setup.py file, you can define various entry points that should be installed as scripts. However, these entry points refer to functions, not files.
Instead of running a script with Python (
python path/to/script.py args...), you can also run a module or package:
python -m example.package args.... For modules (i.e. Python files), you have to do the
if __name__ == '__main__' check and dispatch to your main function. For packages (i.e. directories with an
__init__.py file), you have to create a
__main__.py file as an entry point. It makes sense to put the argument parsing & user interface code here.
This is particularly sensible when adding a command line interface to an existing library. However, it is often elegant to write the central behaviour of an application as a library, and then only wrap that library with a simple user interface. In particular, this layered architecture makes unit testing easier.