Intro to Python Packaging


http://slid.es/edwardliaw/python-packaging


Edward Liaw

2013-12-05

What we'll talk about today


How to install packages


How to set up a development environment


How to make your own packages

The Toolkit


Pip

Package manager that fetches from pypi.python.org


Virtualenv

Create isolated environments of installed packages


Setuptools

Packaging tool that makes installation/distribution easy

Pip


Install it

# Pip is automatically installed in new virtualenvs by the way

# Install setuptools first
curl -O https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
python ez_setup.py

# Install pip via setuptools' easy_install script
easy_install pip

Install something?!
pip install ipython

Virtualenv


Install it

pip install virtualenv

# Or manually
curl -O https://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.10.1.tar.gz
tar xzf virtualenv-1.10.1.tar.gz
cd virtualenv-1.10.1
python setup.py install

Create a new environment

virtualenv ~/.local/python27

# Handy defs for your .bash config
export VIRTUAL_ENV_DISABLE_PROMPT=1
function act-py2() { source ~/.local/python27/bin/activate; }

act-py2
deactivate

Managing venvs with virtualenvwrapper


# Install in base python (not in a virtualenv)
pip install virtualenvwrapper

# For your .bash config
export WORKON_HOME="~/.venvs"
[[ -f "/usr/local/bin/virtualenvwrapper.sh" ]] && source "/usr/local/bin/virtualenvwrapper.sh"

mkdir -p $WORKON_HOME
mkvirtualenv python27
workon python27
deactivate

Benefits

Keeps your venvs in one place
Scripts to create, switch, delete, query installed packages, etc.

Auto-venv switching with autoenv


Switches to a venv when you cd into a directory with an .env file

Small time-saver for developing on many projects (with many venvs)

Overrides cd

Not for me...

Let's make a package!



Read the docs

http://pythonhosted.org/setuptools/setuptools.html


Code

https://github.com/edliaw/demo_project

Getting started



setup.py

Where is your code is located?

Package dependencies?

Installation procedures?

Metadata for uploading to PyPI?

Simple setup.py


from setuptools import setup, find_packages

setup(
name = "demo_project",
version = "0.1",
packages = find_packages(),
)

Install as development package (symlink)
python setup.py develop

Hard install (copy)
python setup.py install

Readme


from setuptools import setup, find_packages

def readme():
with open("README.md") as f:
return f.read()

setup(
name = "demo_project",
version = "0.1",
packages = find_packages(),

long_description = readme(),
)

Metadata for PyPI


from setuptools import setup, find_packages

def readme():
with open("README.md") as f:
return f.read()

setup(
name = "demo_project",
version = "0.1",
packages = find_packages(),

# Metadata
author = "Me",
author_email = "me@gmail.com",
description = "A demonstration of setuptools' packaging system",
license = "None",
keywords = "example",
url = "https://github.com/edliaw/demo_project",
long_description = readme(),
# etc....
)

Directory structure


demo_project/
README.md
setup.py
demo_project/
__init__.py
hello.py

Modules


demo_project/
README.md
setup.py
demo_project/
__init__.py
hello.py
math/
__init__.py
fibonacci.py

Tests


demo_project/
README.md
setup.py
demo_project/
__init__.py
hello.py
math/
__init__.py
fibonacci.py
tests/
__init__.py
test_fibonacci.py
tests/
__init__.py
test_all.py

Scripts


demo_project/
README.md
setup.py
demo_project/
__init__.py
hello.py
math/
__init__.py
fibonacci.py
tests/
__init__.py
test_fibonacci.py
tests/
__init__.py
test_all.py
scripts/
fibonacci

setup.py++


from setuptools import setup, find_packages

setup(
name = "demo_project",
version = "0.1",
packages = find_packages(),
)

Exclusion rules


from setuptools import setup, find_packages

setup(
name = "demo_project",
version = "0.1",
packages = find_packages(exclude=["*.tests", "tests.*", "*.tests.*", "tests"]),
)

Tests


from setuptools import setup, find_packages

setup(
name = "demo_project",
version = "0.1",
packages = find_packages(exclude=["*.tests", "tests.*", "*.tests.*", "tests"]),
test_suite = "demo_project.tests.test_all",
)

Scripts


from setuptools import setup, find_packages

setup(
name = "demo_project",
version = "0.1",
packages = find_packages(exclude=["*.tests", "tests.*", "*.tests.*", "tests"]),
test_suite = "demo_project.tests.test_all",
scripts = ["scripts/fibonacci"],
)

Dependencies


from setuptools import setup, find_packages

setup(
name = "demo_project",
version = "0.1",
packages = find_packages(exclude=["*.tests", "tests.*", "*.tests.*", "tests"]),
test_suite = "demo_project.tests.test_all",
scripts = ["scripts/fibonacci"],

install_requires = [""],
)

Scripts #2

setup(
...
scripts = ["scripts/fibonacci"],
)

Another way of specifying scripts is as entry points to functions:
setup(
...
entry_points = {
'console_scripts' : [
'fibonacci = math.fibonacci.main',
],
'gui_scripts' : [
],
}
)

Python Packaging

By Edward Liaw

Python Packaging

Packaging using pip, setuptools, and virtualenv!

  • 1,461