Python working environment

Foreword

  • CPython 2.7
  • The last versions of tools
  • Links are blue

Packaging

History

  • 2000: distutils
  • 2003: PyPI
  • 2004: setuptools (easy_install, egg)
  • 2007: virtualenv
  • 2008: pip
  • 2008: distribute (fork from setuptools)
  • 2012: distutils2/packaging (*)
  • 2013: New era -- PyPA
  • PEPs, Standarts, Maintenance, Improvements

Installation tool recomendations

  • Use pip to install Python packages from PyPI.
  • Use virtualenv to isolate application specific dependencies from a shared Python installation.
  • Use pip wheel to create a cache of wheel distributions, for the purpose of speeding up subsequent installations.

pip

$ pip install Package
$ pip install "Package>=1.0,<2.0"
$ pip install -U Package
$ pip install -r requirements.txt
$ pip uninstall Package

$ pip freeze
$ pip list
$ pip list -o  # --outdated

$ pip show Package
$ pip search Package

$ pip completion --bash >> ~/.profile
$ pip completion --zsh >> ~/.zprofile

$ pip install --user Package  # global, no sudo, no venv
$ # ~/.local/bin or $(python -m site --user-base)/bin

$ pip install --download=/home/user/.pip/cache Package
$ pip install --no-index --find-links=file:///home/user/.pip/cache Package

$ pip install wheel
$ pip wheel --wheel-dir=/home/user/.pip/wheels Package
$ pip install --find-links=file:///home/user/.pip/wheels Package
$ # wheels
$ pip wheel Package; pip install Package
$ cat ~/.pip/pip.conf
[global]
find-links = file:///home/user/.pip/wheels
wheel-dir = /home/user/.pip/wheels

$ # cache
$ pip install Package
$ cat ~/.pip/pip.conf
[global]
download-cache = /home/user/.pip/cache
find-links = file://home/user/.pip/cache

pip conf

Requirements

Name

  • req.txt
  • requirements.pip
  • requirements.txt

Actually...

$ tree
.
├── mega_project
│   ├── __init__.py
...
├── README.rst
├── requirements
│   ├── base.txt
│   ├── development.txt
│   ├── production.txt
│   └── testing.txt
├── requirements.txt
├── setup.cfg
└── tests
    ├── __init__.py

Because...

$ tree 
...
├── mega_project
│   ├── __init__.py
│   ├── settings
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── development.py
│   │   ├── production.py
│   │   └── testing.py
...

Contents

$ cat requirements.txt
-r requirements/production.txt

$ cat requirements/production.txt
-r base.txt

uWSGI==2.0.6

$ cat requirements/base.txt
# flask
Flask==0.10.1

# flask extensions
Flask-Admin==1.0.8

# deps
Jinja2==2.7.3
MarkupSafe==0.23
WTForms==2.0.1
Werkzeug==0.9.6
itsdangerous==0.24

Rules of Repeatability

  • Pin packages to specific versions ("==")
  • List all dependencies (~"pip freeze")
  • Run "pip install --no-deps -r requirements.txt" (*)

Virtual environments

virtualenv is awesome...

but virtualenvwrapper is more awesome!

Features

  • Organizes all of your virtual environments in one place.
  • Wrappers for managing your virtual environments .
  • Use a single command to switch between environments.
  • Tab completion for commands.
  • User-configurable hooks for all operations.
  • Plugin system for more creating sharable extensions .

Interactive shells

ipython is awesome...

but I like bpython!

Features

  • In-line syntax highlighting.
  • Readline-like autocomplete.
  • Expected parameter list for any Python function.
  • "Rewind" function.
  • Send the code you've entered off to a pastebin.
  • Save the code you've entered to a file.
  • Auto-indentation.

Code style checkers

PEP8

PEP257 - Docstring Conventions

  • Use """triple double quotes""" around docstrings.
  • Use r"""raw triple double quotes""" if you use "\" in docstrings.
  • Use u"""Unicode triple-quoted strings""" for Unicode docstrings.
  • All modules should normally have docstrings.
  • All functions and classes exported by a module should have docstrings.
  • Public methods (including the __init__ constructor) should have docstrings.
  • A package may be documented in the module docstring of the __init__.py file in the package directory.

One-line Docstrings

def is_string(obj):
    """Check if 'obj' is a string."""
    return isinstance(obj, basesring)
  • Triple quotes are used even though the string fits on one line.
  • The closing quotes are on the same line as the opening quotes.
  • There's no blank line either before or after the docstring.
  • The docstring is a phrase ending in a period.
  • It prescribes the function or method's effect as a command ("Do this", "Return that"), not as a description; e.g. don't write "Returns the pathname ...".

Tools

Imports

  • Future
  • Python Standard Library
  • Third Party
  • Current Python Project
  • Explicitly Local (. before import, as in: from . import x)

How do you sort multi line imports?

# grid
from third_party import (lib1, lib2, lib3,
                         lib4, lib5, ...)
# vertical
from third_party import (lib1,
                         lib2,
                         lib3
                         lib4,
                         lib5,
                         ...)
# vertical hanging
from third_party import (
    lib1,
    lib2,
    lib3,
    lib4,
)
# hanging grid
from third_party import (
    lib1, lib2, lib3, lib4,
    lib5, ...)
# own line
from third_party import lib1
from third_party import lib2
from third_party import lib3
...

Project templates

Template

$ tree -a -L 3 cookiecutter-yad/
cookiecutter-yad/
├── cookiecutter.json
├── {{ cookiecutter.repo_name }}
│   ├── {{ cookiecutter.project_name }}
│   │   ├── apps
│   │   ├── {{ cookiecutter.project_name }}
│   │   └── manage.py
│   ├── .gitignore
│   ├── README.rst
│   ├── requirements
│   │   ├── base.txt
│   │   ├── dev.txt
│   │   ├── production.txt
│   │   └── testing.txt
│   └── requirements.txt
├── .gitignore
├── LICENSE
└── README.rst
$ cat cookiecutter-yad/cookiecutter.json 
{
	"repo_name": "RepoName",
	"project_name": "project_name",
	"app_name": "app_name",

	"author_name": "Your Name",
	"author_email": "your@email"
}
$ cookiecutter cookiecutter-yad/ 
repo_name (default is "RepoName")? awesome       
project_name (default is "project_name")? awesome
app_name (default is "app_name")? users
author_name (default is "Your Name")? Yan 
author_email (default is "your@email")?

New project

$ tree -a -L 3 awesome/
awesome/
├── awesome
│   ├── apps
│   │   ├── common
│   │   ├── __init__.py
│   │   └── users
│   ├── awesome
│   │   ├── __init__.py
│   │   ├── settings
│   │   ├── urls.py
│   │   └── wsgi.py
│   └── manage.py
├── .gitignore
├── README.rst
├── requirements
│   ├── base.txt
│   ├── dev.txt
│   ├── production.txt
│   └── testing.txt
└── requirements.txt

IDE

One love

Gotta catch 'em all!

PyCharm is awesome!

Misc

ssh_config

$ cat ~/.ssh/config
Host infograph
    User yan
    Port 2222
    HostName infograph.example.com
    IdentityFile ~/.ssh/infograph_rsa

$ # the following lines do the same
$ ssh -i ~/.ssh/infograph_rsa -p 2222 yan@infograph.example.com
$ ssh infograph

Resources

Thanks

Python working environment

By Yan Kalchevskiy

Python working environment

Tools that I use and how I use them

  • 2,981