Step 2: Python Package Setup

Now that we’ve got Eclipse up and running it is time to create our empty Python project. In our case we want the project to be ready for some automated package building so that we can deploy it to PyPi.org or other Python package providers.

To set up an empty project the process is pretty simple. (I’m building on Debian/Ubuntu Linux and using “python3” instead of “python” so your setup may vary a little.)

First, we need to decide which non-Python files we want to include in our project. In my case I plan to include a license, changelog, and readme. I prefer the markdown syntax. I also prefer the defacto standard file names as well (all caps) and those will go in the root folder.

For our setup configuration we’ll specify that with a setup.cfg file. The setup.cfg is used by PyPi to build your program so the options here are pretty advanced. My setup however is fairly basic so have a look.

[metadata]
name = karen
author = lnxusr1
author_email = lnxusr1@localhost
version = attr: src.karen.VERSION
description = Project Karen
long-description = file: README.md
long_description_content_type = text/markdown
keywords = Artificial Intelligence, AI, Personal Assistant
license = MIT
home-page = https://projectkaren.ai
classifiers =
    License :: OSI Approved :: MIT License
    Programming Language :: Python :: 3
    Operating System :: OS Independent
project_urls = 
    Bug Tracker = https://github.com/lnxusr1/karen/issues
    Changelog = https://github.com/lnxusr1/karen/blob/master/CHANGELOG.md

#[build-system]
#requires = 
#    {install_requires}

[options]
python_requires = >= 3.6
zip_safe = false
include_package_data = true
test_suite = tests
setup_requires =
    setuptools
    # setuptools >=30.3.0     # minimal version for `setup.cfg`
    # setuptools >=38.3.0     # version with most `setup.cfg` bugfixes
#install_requires =
#    {install_requires}
#tests_require =
#    {tests_require}
package_dir=
    =src
packages=find:

[options.packages.find]
where=src

Then we need a setup.py file which is very, very simple. Here are the contents of my setup.py file in the root of my project. It’s just two lines.

import setuptools

setuptools.setup()

The setup.py will read the configuration out of the setup.cfg file so no need to duplicate our configuration in this file.

Lastly, we need to add a src folder which is where we will put our actual module. I added a module called “karen” and an “__init__.py” file with a version in it. Pretty simple, but here’s my module.

# version as tuple for simple comparisons 
VERSION = (0, 5, 1) 
# string created from tuple to avoid inconsistency 
__version__ = ".".join([str(x) for x in VERSION])

And here is what my package looks like:

If you haven’t already installed the setuptools package then you need to do that (“pip3 install setuptools”), but once it’s installed we can test out our setup.py and try to build our module.

$ python3 setup.py --version
0.5.1

And you can build your package with this command:

$ python3 setup.py sdist bdist_wheel
running sdist
running egg_info
creating src/karen.egg-info
writing src/karen.egg-info/PKG-INFO
writing dependency_links to src/karen.egg-info/dependency_links.txt
writing top-level names to src/karen.egg-info/top_level.txt
writing manifest file 'src/karen.egg-info/SOURCES.txt'
reading manifest file 'src/karen.egg-info/SOURCES.txt'
writing manifest file 'src/karen.egg-info/SOURCES.txt'
running check
creating karen-0.5.1
creating karen-0.5.1/src
creating karen-0.5.1/src/karen
creating karen-0.5.1/src/karen.egg-info
copying files to karen-0.5.1...
copying README.md -> karen-0.5.1
copying pyproject.toml -> karen-0.5.1
copying setup.cfg -> karen-0.5.1
copying setup.py -> karen-0.5.1
copying src/karen/__init__.py -> karen-0.5.1/src/karen
copying src/karen.egg-info/PKG-INFO -> karen-0.5.1/src/karen.egg-info
copying src/karen.egg-info/SOURCES.txt -> karen-0.5.1/src/karen.egg-info
copying src/karen.egg-info/dependency_links.txt -> karen-0.5.1/src/karen.egg-info
copying src/karen.egg-info/not-zip-safe -> karen-0.5.1/src/karen.egg-info
copying src/karen.egg-info/top_level.txt -> karen-0.5.1/src/karen.egg-info
Writing karen-0.5.1/setup.cfg
creating dist
Creating tar archive
removing 'karen-0.5.1' (and everything under it)
running bdist_wheel
running build
running build_py
creating build
creating build/lib
creating build/lib/karen
copying src/karen/__init__.py -> build/lib/karen
installing to build/bdist.linux-x86_64/wheel
running install
running install_lib
creating build/bdist.linux-x86_64
creating build/bdist.linux-x86_64/wheel
creating build/bdist.linux-x86_64/wheel/karen
copying build/lib/karen/__init__.py -> build/bdist.linux-x86_64/wheel/karen
running install_egg_info
Copying src/karen.egg-info to build/bdist.linux-x86_64/wheel/karen-0.5.1-py3.7.egg-info
running install_scripts
adding license file "LICENSE.md" (matched pattern "LICEN[CS]E*")
creating build/bdist.linux-x86_64/wheel/karen-0.5.1.dist-info/WHEEL
creating 'dist/karen-0.5.1-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it
adding 'karen/__init__.py'
adding 'karen-0.5.1.dist-info/LICENSE.md'
adding 'karen-0.5.1.dist-info/METADATA'
adding 'karen-0.5.1.dist-info/WHEEL'
adding 'karen-0.5.1.dist-info/top_level.txt'
adding 'karen-0.5.1.dist-info/RECORD'
removing build/bdist.linux-x86_64/wheel

Download the empty Python Package
(empty-python-project.zip)