In this lesson, we'll see how to create, install, and distribute your own PYTHON packages, whether for use internally or in sharing with a broader, more open community.
An overview of creating and installing python packages serves to prepare for conda packages in two ways:
- a python package provides the basic ingredient needed to create a conda package
- the process of python package creation introduces concepts needed to understand conda packaging
- Building a Python Package
- Installing a Python Package
- 2-Step Install
- Step 1: Create a
setup.py
file - Step 2: Execute the setup.py install command
- Step 1: Create a
- Install Paths
- Uninstalling Python Packages
- 2-Step Install
Below is an example of a simple python module called constants.py
.
print("Welcome to the constants.py module")
import math
E = 2.71828
PI = 3.14159
def compute_pi():
return 4.0*math.atan(1.0)
def compute_e():
sum = 0
for n in range(10):
sum += 1/math.factorial(n)
return sum
def print_const(x):
print("The value of your constant is ", x)
return None
Exercise: Create a python module
Using your favorite text editor, create a new file `constants.py` within the `Conda` lesson directory, and paste the python code above into the file.
This module contains a print statement, one import, two "data attributes", E
and PI
, and three functions, compute_pi()
, compute_e()
, and print_const()
.
This module is executable from the system shell.
cd Conda
python constants.py
This module is also executable from the python shell; it is not "compiled" before it is used.
cd Conda
python
>>> exec( open("constants.py").read() )
Exercise: Execute the module as a script
Instead of the python shell, execute the `constants.py` module using the IPython shell, using the `%run` magic followed by the file name.
From the python shell one can import this file as a python module, and thus access its attributes and call its functions:
cd Conda
python
>>> import constants
>>> constants.PI
3.14
>>> constants.compute_pi()
3.1415926535897931
Exercise: Import the module
Using the IPython shell, launched either from the Jupyter home tab or your system shell, import the constants file as a module. Test the import by calling the `constants.compute_e()` method.
In python, building a large library of reusable code starts with organizing your code into modules, which are then further organized into a python package.
A python package is a collection of
- one or more python modules (like
constants.py
) - a build/install file called
setup.py
- other optional and customary "meta-data files" like
README.txt
These are organized into a particular directory structure. An example of a very simple python package is given below:
Desktop/
my_package/
constants.py
setup.py
README.txt
LICENSE.txt
Exercise: Create a python package
Create the file tree shown above. Use the previously created constants.py. Create but otherwise leave all other files empty for now.
Exercise: Create a `setup.py` file
Edit the empty `setup.py` file and paste into it the code shown below.
from setuptools import setup
setup( name='constants',
version='0.0.1',
py_modules=['constants',],
)
Exercise: Add meta-data to your python package
Edit the `README.txt` and `LICENSE.txt` files. For the `README`, add a brief description of `constants.py`. For the `LICENSE` file, add the following text within it:
Licensees may copy, distribute, display and perform the work and make derivative works and remixes based on it only if they give the author or licensor the credits (attribution) in the manner specified by these.
The complete details of the process by which a python package is installed are beyond the scope of this present lesson. But the basics are simple: the contents of the my_package
directory are in essense copied into a directory whose location will be known to any instance of the python interpreter you launch on your computer.
The most common method for safely and reproducibly installing a python package are outlined as follows:
from setuptools import setup
setup( name='constants',
version='0.0.1',
py_modules=['constants',],
)
python setup.py install
or
pip install .
...not yet!
For a software package that includes compiled source code, like a python "extension" package or a C library, your "build" process would include an actual compilation step, possibly involving a Makefile (Linux), CMake file (Linux, Mac, Windows), or a VS Project file (Windows).
Exercise: Make a more complete `setup.py`
Edit your `setup.py` file so that it reads as shown below:
Here is a more complete setup.py
example:
from setuptools import setup
setup(
name='constants',
version='0.0.1',
license='CC BY-NC-SA 4.0',
long_description=open('README.txt').read(),
py_modules=['constants',],
)
Exercise: Update your LICENCE.txt file
Search online for the license called "CC BY-NC-SA 4.0" to discover what it is if you have not heard of it. Replace all text within your `LICENSE.txt` with that of the "CC" license found online.
Review the following description of Creative Commons as well: https://en.wikipedia.org/wiki/Creative_Commons_license
Exercise: Use `setup.py` to install the package
Execute the `python setup.py install` command. Then test the install by moving to `Desktop`, launching a new python interpreter, and trying to `import constants`:
cd Desktop
python
>>> import constants
Welcome to the constants.py module!
>>> constants.PI
3.14159
>>> constants.compute_pi()
3.1415926535897931
How does the python import
know where to find where the package was installed?
This is done through the sys.path
directory list:
>>> import sys
>>> sys.path
This sys.path
is analogous to the system PATH
variable.
It is the list of directories on your file system wherein python will search for python modules or python packages when you try to import
them.
When you installed your python package, its files will be located within one of the directories listed in sys.path
.
Note: It is best to never try to copy files manually into any of the directories listed in sys.path
as it is very easy to break something in the process, and it is very hard to reproduce the results even when successful.
Exercise: View path order in `sys.path`
Inspect the file path search order in `sys.path` by running the folling commands from the python shell:
python
>>> import sys
>>> sys.path
Exercise: View python package install paths
Compare the `sys.path` file paths to those of the python package `site`, execute the following commands from within your python interpreter:
python
>>> import site
>>> site.USER_SITE
/Users/juser/.local/lib/python3.5/site-packages
>>> site.USER_BASE
/Users/juser/.local
>>> site.PREFIXES
/Users/juser/anaconda
This is where things get painful. There is no python setup.py uninstall
. You must find and manually delete all the installed files.
One helpful tool is to store the names of all the files at the time of install:
python setup.py install --record installed_files.txt
Contents of installed_files.txt
/Users/juser/anaconda/lib/python3.5/site-packages/constants-0.0.1-py3.5.egg
Python package left-overs
It's even a bit more involved than that. Inspect the contents of the directory where the setup.py file lives, and you'll find many other intermediate file artifacts left-over from the build and install process.
The `.egg` file format
The .egg
file is a distribution format for Python packages. It’s just an alternative to a source code distribution or an executable binary. For pure Python, the .egg
file is completely cross-platform. The .egg
file itself is like a .zip
file. It contains source code, and meta-data, and other resources.
Exercise: Manually remove the install file
Uninstall the package by manually deleting the file listed in `installed_files.txt`. Test this "uninstall" by then launching a python shell and trying to import the package as `import constants`.
In this lesson we saw....
- Building a Python module
- Building a Python package