Its mainly used to define the additional scripts you'll be using in your package. Here's a snippet from the official documentation on python-packaging:

#!/usr/bin/env python
import funniest 
print funniest.joke() 

Then we can declare the script in setup() like this:

setup(
    ...
    scripts=['bin/funniest-joke'],
    ... 
    ) 

When we install the package, setuptools will copy the script to our PATH and make it available for general use. This has advantage of being generalizeable to non-python scripts, as well: funniest-joke could be a shell script, or something completely different.

Answer from worker_bee on Stack Overflow
🌐
JetBrains
jetbrains.com β€Ί help β€Ί pycharm β€Ί creating-and-running-setup-py.html
Create and run setup.py | PyCharm Documentation
August 17, 2026 - PyCharm provides an action that helps create setup.py script, intended for building, distributing, and installing modules.
🌐
Python Packaging
packaging.python.org β€Ί guides β€Ί distributing-packages-using-setuptools
Packaging and distributing projects - Python Packaging User Guide
Alternatively, if you must use python setup.py, then you need to pass the --old-and-unmanageable option. Although setup() supports a scripts keyword for pointing to pre-made scripts to install, the recommended approach to achieve cross-platform compatibility is to use Creating executable scripts ...
🌐
pytz
pythonhosted.org β€Ί an_example_pypi_project β€Ί setuptools.html
Getting Started With setuptools and setup.py β€” an_example_pypi_project v0.0.5 documentation
sdist: This create a raw source distribution which someone can download and run python setup.py directly. ... A key point here is you need to run these commands with the version of python you want to support. We’ll cover this in the Putting It All Together With The Full Windows Script below.
🌐
Readthedocs
python-packaging.readthedocs.io β€Ί en β€Ί latest β€Ί command-line-scripts.html
Command Line Scripts β€” Python Packaging Tutorial
funniest/ funniest/ __init__.py ... setup.py bin/ funniest-joke ... ... When we install the package, setuptools will copy the script to our PATH and make it available for general use.: ... This has advantage of being generalizeable to non-python scripts, as well: funniest-joke could be a shell script, or something completely different.
🌐
PyPA
setuptools.pypa.io β€Ί en β€Ί latest β€Ί userguide β€Ί quickstart.html
Quickstart - setuptools 84.0.0 documentation
Prior to pip v21.1, a setup.py script was required to be compatible with development mode. With late versions of pip, projects without setup.py may be installed in this mode. If you have a version of pip older than v21.1 or is using a different packaging-related tool that does not support PEP 660, you might need to keep a setup.py file in your repository if you want to use editable installs. ... When building from source code (for example, by python ...
🌐
Data Science for Everyone
matthew-brett.github.io β€Ί pydagogue β€Ί installing_scripts.html
Installing python scripts β€” pydagogue 0.2 documentation
We now depend on setuptools at install time to write the console script stuff and at run time in finding the installed scripts via pkg_resources (see above and below). We run an install into a virtualenv (Unix again): virtualenv venv . venv/bin/activate python setup.py install
Find elsewhere
🌐
Python
docs.python.org β€Ί 3.11 β€Ί distutils β€Ί setupscript.html
2. Writing the Setup Script β€” Python 3.11.16 documentation
The packages option tells the Distutils to process (build, distribute, install, etc.) all pure Python modules found in each package mentioned in the packages list. In order to do this, of course, there has to be a correspondence between package names and directories in the filesystem. The default correspondence is the most obvious one, i.e. package distutils is found in the directory distutils relative to the distribution root. Thus, when you say packages = ['foo'] in your setup script, you are promising that the Distutils will find a file foo/__init__.py (which might be spelled differently on your system, but you get the idea) relative to the directory where your setup script lives.
🌐
DevTut
devtut.github.io β€Ί python β€Ί setup-py.html
Python - setup.py
from distutils.core import setup setup(name='foo', version='1.0', py_modules=['foo'], ) To create a source distribution for this module, you would create a setup script, setup.py, containing the above code, and run this command from a terminal:
🌐
ROS
docs.ros.org β€Ί en β€Ί jade β€Ί api β€Ί catkin β€Ί html β€Ί user_guide β€Ί setup_dot_py.html
Handling of setup.py β€” catkin 0.6.19 documentation
If your ROS package contains python modules and scripts to install, you need to define the installation process and a way to make the scripts accessible in the develspace. The python ecosystem defines installation standards in the distutils or setuputils libraries. With those libraries, packages define the installation files in a file called setup.py in the project root.
Top answer
1 of 10
1229

setup.py is a Python file, the presence of which is an indication that the module/package you are about to install has likely been packaged and distributed with Distutils, which is the standard for distributing Python Modules.

This allows you to easily install Python packages. Often it's enough to write:

$ pip install . 

pip will use setup.py to install your module. Avoid calling setup.py directly.

2 of 10
834

It helps to install a python package foo on your machine (can also be in virtualenv) so that you can import the package foo from other projects and also from [I]Python prompts.

It does the similar job of pip, easy_install etc.,


Using setup.py

Let's start with some definitions:

  • Package - A folder/directory that contains __init__.py file.
  • Module - A valid python file with .py extension.
  • Distribution - How one package relates to other packages and modules.

Let's say you want to install a package named foo. Then you do,

$ git clone https://github.com/user/foo
$ cd foo
$ python setup.py install

Instead, if you don't want to actually install it but still would like to use it. Then do,

$ python setup.py develop

This command will create symlinks to the source directory within site-packages instead of copying things. Because of this, it is quite fast (particularly for large packages).


Creating setup.py

If you have your package tree like,

foo
β”œβ”€β”€ foo
β”‚   β”œβ”€β”€ data_struct.py
β”‚   β”œβ”€β”€ __init__.py
β”‚   └── internals.py
β”œβ”€β”€ README
β”œβ”€β”€ requirements.txt
└── setup.py

Then, you do the following in your setup.py script so that it can be installed on some machine:

from setuptools import setup

setup(
   name='foo',
   version='1.0',
   description='A useful module',
   author='Man Foo',
   author_email='foomail@foo.example',
   packages=['foo'],  #same as name
   install_requires=['wheel', 'bar', 'greek'], #external packages as dependencies
)

Instead, if your package tree is more complex like the one below:

foo
β”œβ”€β”€ foo
β”‚   β”œβ”€β”€ data_struct.py
β”‚   β”œβ”€β”€ __init__.py
β”‚   └── internals.py
β”œβ”€β”€ README
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ scripts
β”‚   β”œβ”€β”€ cool
β”‚   └── skype
└── setup.py

Then, your setup.py in this case would be like:

from setuptools import setup

setup(
   name='foo',
   version='1.0',
   description='A useful module',
   author='Man Foo',
   author_email='foomail@foo.example',
   packages=['foo'],  #same as name
   install_requires=['wheel', 'bar', 'greek'], #external packages as dependencies
   scripts=[
            'scripts/cool',
            'scripts/skype',
           ]
)

Add more stuff to (setup.py) & make it decent:

from setuptools import setup

with open("README", 'r') as f:
    long_description = f.read()

setup(
   name='foo',
   version='1.0',
   description='A useful module',
   license="MIT",
   long_description=long_description,
   author='Man Foo',
   author_email='foomail@foo.example',
   url="http://www.foopackage.example/",
   packages=['foo'],  #same as name
   install_requires=['wheel', 'bar', 'greek'], #external packages as dependencies
   scripts=[
            'scripts/cool',
            'scripts/skype',
           ]
)

The long_description is used in pypi.org as the README description of your package.


And finally, you're now ready to upload your package to PyPi.org so that others can install your package using pip install yourpackage.

At this point there are two options.

  • publish in the temporary test.pypi.org server to make oneself familiarize with the procedure, and then publish it on the permanent pypi.org server for the public to use your package.
  • publish straight away on the permanent pypi.org server, if you are already familiar with the procedure and have your user credentials (e.g., username, password, package name)

Once your package name is registered in pypi.org, nobody can claim or use it. Python packaging suggests the twine package for uploading purposes (of your package to PyPi). Thus,

  1. the first step is to locally build the distributions using:

    # prereq: wheel (pip install wheel)
    $ python setup.py sdist bdist_wheel
    
  2. then using twine for uploading either to test.pypi.org or pypi.org:

    $ twine upload --repository testpypi dist/*
    username: ***
    password: ***
    

It will take few minutes for the package to appear on test.pypi.org. Once you're satisfied with it, you can then upload your package to the real & permanent index of pypi.org simply with:

$ twine upload dist/*

Optionally, you can also sign the files in your package with a GPG by:

$ twine upload dist/* --sign

Bonus Reading:

  • See a sample setup.py from a real project here: torchvision-setup.py

  • PEP 517, setuptools

  • why twine? using twine

🌐
Medium
medium.com β€Ί @christina.jacob.koikara β€Ί the-setup-py-16eefeb2f6f2
The setup.py. Packaging Python modules using… | by Christina Jacob | Medium
November 10, 2023 - The inner my_module directory is where your Python module code resides. setup.py is the script that contains the package metadata and instructions for setuptools.
🌐
Reddit
reddit.com β€Ί r/python β€Ί how does setup.py actually work?
r/Python on Reddit: How does setup.py actually work?
January 3, 2015 -

I'm deep in packaging hell at the moment, because I'm shipping Cython modules which other Cython modules will depend on at compile time. It's an unusual use-case, Python packaging is deeply broken, so okay, I'll have pain.

But: what is even going on when I execute

python setup.py install

Is the file executed top-to-bottom as normal, until it enters the setup() function? Does setuptools do anything unseemly/magical? When does the "install" argument get read from the command line? What determines what order the dependencies start getting installed?

Top answer
1 of 5
12

Is the file executed top-to-bottom as normal, until it enters the setup() function?

Yes, of course; it's just a Python script.

Does setuptools do anything unseemly/magical?

It isn't specially recognized by the Python interpreter, or anything like that, if that's what you mean. I'll leave you to judge whether any of what distutils or setuptools do is is black, black magic.

When does the "install" argument get read from the command line? But: what is even going on when I execute python setup.py install?

setup.py is just a script. It, by convention, includes a call to the setup() function defined in distutils (or setuptools, etc.). This is a totally normal Python function call. The arguments that you pass are metadata about the package, what Python and non-Python files should be included, how any native code should be built, what entry point wrappers should be installed, and so forth.

If I had to guess without looking at the source, I would guess that something like argparse is used to actually do the work of reading "install" from the command line. These arguments are available as sys.argv throughout a script's execution.

Documentation for setuptools is here. The source (including the implementation of setup()) is available here.

2 of 5
7

Welcome to Golang! Just kidding! Most setup scripts use distutils (or setuptools) in conjunction with their setup.py script. Here is probably the best example I can find :

https://docs.python.org/3.3/distutils/introduction.html#a-simple-example

Also if you are developing for windows take a look at:

bdist_wininst

Edit: I unfortunetly not quite sure of the order in which packages are installed I imagine it retains the order of how it is listed in the setup script???

🌐
Socket
socket.dev β€Ί glossary β€Ί setup-py-python
Glossary: setup.py (Python) - Socket.dev
setup.py is a Python script used for distributing Python packages, handling dependencies, and facilitating easy installation and sharing of code.
🌐
GitHub
github.com β€Ί rsmith-nl β€Ί setup-py-script
GitHub - rsmith-nl/setup-py-script: Setup scripts to install simple scripts or self-contained Python application archives. Β· GitHub
So these setup scripts are an attempt to do things differently. The goal is to provide (simple) installation for standalone scripts that may or may not be compressed and that may or may not use a GUI.
Author: rsmith-nl
🌐
Xebia
xebia.com β€Ί home β€Ί blog β€Ί a practical guide to using setup.py
A Practical Guide To Using Setup.py | Xebia
June 22, 2026 - setup.py is a Python script that describes your project and its dependencies, making it easy to install your package consistently across different machines and platforms. It defines essential metadata like the package name, version, and required ...
🌐
Medium
godwin1100.medium.com β€Ί python-packaging-setup-py-ae04b3d41653
Python Packaging: Setup.py. Packaging Python projects efficiently… | by Shivam Panchal | Medium
September 2, 2024 - The setup.py file plays a central role in this process. It is a Python script traditionally used to configure the various aspects of a Python package.
🌐
Lbl
davis.lbl.gov β€Ί Manuals β€Ί PYTHON-2.3.3 β€Ί dist β€Ί setup-script.html
3 Writing the Setup Script
If directory is a relative path, it is interpreted relative to the installation prefix (Python's sys.prefix for pure-Python packages, sys.exec_prefix for packages that contain extension modules). Each file name in files is interpreted relative to the setup.py script at the top of the package source distribution.
🌐
Delft Stack
delftstack.com β€Ί home β€Ί howto β€Ί python β€Ί python setup.py
How to Use Python setup.py | Delft Stack
March 11, 2025 - At its core, setup.py is a Python script that contains instructions on how to install a package. This file is part of the Python Packaging Authority’s guidelines and is essential for distributing Python projects.