How to Package Python Dependencies for Publication
If you’re packaging a Python package for publication, how do you ensure that all of the required dependencies are included? Just like pip is the standard package manager for Python, setup.py is the heart and center of Python projects installed with pip. Simply put, setup.py is a build script template distributed with Python’s setuptools package.
Setuptools is a package development process library and utility for building Python projects based on packages and their dependencies listed in a setup.py script. A Python file that relies only on the standard library can be redistributed and reused without the need to use setuptools. But for projects that consist of multiple files, need additional libraries, or need a specific version of Python, setuptools will be required.
Update Python Tools
The first step is a best practice: make sure your tools are up to date.
$ python -m pip install --upgrade pip setuptools
The following script is an example of how to create a setup.py script for your project. The script spells out the information you need to provide, including:
- Project name – enter a name for your project in quotes
- Packages to include in the distribution – the find_packages(‘,’) default argument will incorporate all packages that include an __init__.py file and are located in the local directory where setup.py is installed
- Project version number – enter a version number for the project in quotes
- List a license for the project – enter the name of the license you are licensing your project for use under in quotes
- Short description of your library – enter a brief description of your project in quotes
- Long description of your library – enter a more detailed description of your project either in text or using markdown
- Your name – enter your name in quotes to denote who the author is
- Your email address – optionally provide an email address in quotes where users can contact you
- Link to your github repository or website – optionally provide a link to your project’s repo
- Download Link from where the project can be downloaded from – provide an URL to your project’s source code in quotes
- List of keywords – provide a list of keywords in square brackets associated with your project to make it easier to search for
- List project dependencies – provide a list of all the dependencies your project requires in square brackets. The easiest way to provide this is to copy and paste from the install_requires section (see below).
- https://pypi.org/classifiers – provide a list of all classifiers that apply to your project in square brackets. You can find a comprehensive list of classifiers at https://pypi.org/classifiers
from distutils.core import setup from setuptools import find_packages import os # Optional project description in README.md: current_directory = os.path.dirname(os.path.abspath(__file__)) try: with open(os.path.join(current_directory, 'README.md'), encoding='utf-8') as f: long_description = f.read() except Exception: long_description = '' setup( # Project name: name='', # Packages to include in the distribution: packages=find_packages(','), # Project version number: version='', # List a license for the project, eg. MIT License license='', # Short description of your library: description='', # Long description of your library: long_description=long_description, long_description_content_type='text/markdown', # Your name: author='', # Your email address: author_email='', # Link to your github repository or website: url='', # Download Link from where the project can be downloaded from: download_url='', # List of keywords: keywords=, # List project dependencies: install_requires=, # https://pypi.org/classifiers/ classifiers= )
install_requires is a section within the setup.py file in which you need to input a list of the minimum dependencies needed for a project to run correctly. When pip runs setup.py, it will install all of the dependencies listed in install_requires.
For example, if your project includes matplotlib, you’ll need to list it, as well as its dependency of numpy in install_requires as shown below:
setup( ... install_requires=[ '<matplotlib>', '<numpy>' ] ...) Example of Install_requires with Platform Specific Dependencies
You can modify install_requires by adding in platform-specific and version-specific dependencies, depending on the environment that a project is to be installed on. For instance, if our previous example included matplotlib v3.2.1 and numpy v1.17.4 on Python 3.6.6 for Linux, we could specify:
setup( ... install_requires=[ "<matplotlib>;python_version<'<3.6.6>'", "<numpy> >= <1.17.4>;platform_system=='<Linux>'" ] ...)
To install a setup.py file including dependencies listed in install_inquires:
$ python setup.py install
When the command is run, all of the dependencies not already installed will be downloaded, built (if necessary), and installed. Any scripts that require specific dependencies at runtime will be installed with wrappers that ensure the correct versions are added to sys.path (system path).
Dependency Not Found in PyPI
If your project has a dependency requirement that is not currently in the Python Package Index (PyPI), you can still include them if they can be accessed via http and are packaged as either an egg, .py file, or a VCS (Version Control System) repository, such as Git or Subversion.
In order to download dependencies not found in PyPI, you will need to add URLs to a dependency_links section under setup() in the setup.py file. Assuming that the dependencies are packaged correctly, they will be automatically installed:
setup( ... dependency_links=['http://github.com/<username>/<reponame>/tarball/master#egg=<packagename>-<version#>'] ...)
To check a dependency not found in PyPI, replace – with _ in the package name and version # in the dependency_links argument:
Packaging Python for Windows and Mac
In some cases, it may want to redistribute your Python code as:
- Installers – if you have a Python distribution you want to make available to other developers, or else have a need to perform silent installations over a network, you may want to create an MSI, PKG or tarball
- Executables – if you want to distribute your Python code to Windows users so they can just double-click in order to run it on their system, you may want to create an EXE file
While there are a number of different tools you can use to create installers, they typically require:
- Multiple tools, one for each operating system (OS) you want to deploy to
- Expertise in each target operating system you want to support
Consider using the ActiveState Platform instead, which will automatically package your Python distribution for deployment on Windows (MSI), Mac (PKG) and Linux (TAR), without requiring OS expertise. Create a free account to get started today.
If you prefer to wrap your Python code as a Windows executable, there are a number of tools you can use, including py2exe and cx_freeze. For more information, refer to our blog post How to Convert .py to .exe
The ActiveState Platform is a cloud-based build automation and dependency management tool for Python. It provides dependency resolution for:
- Python language cores, including Python 2.7 and Python 3.5+
- Python packages and their dependencies, including:
- Transitive dependencies (ie., dependencies of dependencies)
- Linked C and Fortran libraries, so you can build data science packages
- Operating system-level dependencies for Windows, Linux, and macOS
- Shared dependencies (ie., OpenSSL)
The ActiveState Platform is the only Python package management solution that not only resolves dependencies but also provides workarounds for dependency conflicts.
Simply following the instruction prompts will resolve the conflict, eliminating dependency hell.
You can try the ActiveState Platform for free by creating an account using your email or your GitHub credentials. Start by creating a new Python project, pick the latest version that applies to your project, your OS and start to add & install packages. Or start by simply importing your requirements.txt file and creating a Python version with all the Python libraries you need.
Conclusions: The Future of Python Package & Dependency Management
If you’re like most Python developers, you probably maintain multiple tools, build environments, and other solutions in order to address the issues that a single tool, the ActiveState Platform can solve today. By adopting the ActiveState Platform, you can:
- Increase the security of your Python environments
- Improve the transparency of your open source supply chain
- Eliminate dependency hell
- Reduce “works on my machine” issues
Ultimately, developers that are willing to adopt the ActiveState Platform for Python packaging will spend less time wrestling with tooling and more time focused on doing what they do best: coding.
Just run the following command to install Python 3.9 and our package manager, the State Tool:
powershell -Command "& $([scriptblock]::Create((New-Object Net.WebClient).DownloadString('https://platform.activestate.com/dl/cli/install.ps1'))) -activate-default ActiveState-Labs/Python-3.9Beta"
sh <(curl -q https://platform.activestate.com/dl/cli/install.sh) --activate-default ActiveState-Labs/Python-3.9Beta
Now you can run state install <packagename>. Learn more about how to use the State Tool to manage your Python environment.